History

Merge tag 'driver-core-7.2-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/driver-core/driver-core

Pull driver core updates from Danilo Krummrich: "Deferred probe: - Fix race where deferred probe timeout work could be permanently canceled by using mod_delayed_work() - Fix missing jiffies conversion in deferred_probe_extend_timeout() - Guard timeout extension with delayed_work_pending() to prevent premature firing - Use system_percpu_wq instead of the deprecated system_wq - Update deferred_probe_timeout documentation device: - Replace direct struct device bitfield access (can_match, dma_iommu, dma_skip_sync, dma_ops_bypass, state_synced, dma_coherent, of_node_reused, offline, offline_disabled) with flag-based accessors using bit operations - Reject devices with unregistered buses - Delete unused DEVICE_ATTR_PREALLOC() - Add low-level device attribute macros with const show/store callbacks, allowing device attributes to reside in read-only memory - Move core device attributes to read-only memory - Constify group array pointers in driver_add_groups() / driver_remove_groups(), struct bus_type, and struct device_driver device property: - Fix fwnode reference leak in fwnode_graph_get_endpoint_by_id() - Initialize all fields of fwnode_handle in fwnode_init() - Provide swnode_get()/swnode_put() wrappers around kobject_get/put() - Allow passing struct software_node_ref_args pointers directly to PROPERTY_ENTRY_REF() driver_override: - Migrate amba, cdx, vmbus, and rpmsg to the generic driver_override infrastructure, fixing a UAF from unsynchronized access to driver_override in bus match() callbacks - Remove the now-unused driver_set_override() firmware loader: - Fix recursive lock deadlock in device_cache_fw_images() when async work falls back to synchronous execution - Fix device reference leak in firmware_upload_register() platform: - Pass KBUILD_MODNAME through the platform driver registration macro to create module symlinks in sysfs for built-in drivers; move module_kset initialization to a pure_initcall and tegra cbb registration to core_initcall to ensure correct ordering - Pass THIS_MODULE implicitly through a coresight_init_driver() macro sysfs: - Upgrade OOB write detection in sysfs_kf_seq_show() from printk to WARN - Add return value clamping to sysfs_kf_read() Rust: - ACPI: Fix missing match data for PRP0001 by exporting acpi_of_match_device() - Auxiliary: Replace drvdata() with dedicated registration data on auxiliary_device. drvdata() exposed the driver's bus device private data beyond the driver's own scope, creating ordering constraints and forcing the data to outlive all registrations that access it. Registration data is instead scoped structurally to the Registration object, making lifecycle ordering enforced by construction rather than convention. - Rust-native device driver lifetimes (HRT): Allow Rust device drivers to carry a lifetime parameter on their bus device private data, tied to the device binding scope -- the interval during which a bus device is bound to a driver. Device resources like pci::Bar<'a> and IoMem<'a> can be stored directly in the driver's bus device private data with a lifetime bounded by the binding scope, so the compiler enforces at build time that they do not outlive the binding. This removes Devres indirection from every access site and eliminates try_access() failure paths in destructors. Bus driver traits use a Generic Associated Type (GAT) Data<'bound> to introduce the lifetime on the private data, rather than parameterizing the Driver trait itself. Auxiliary registration data, where the lifetime is not introduced by a trait callback but must be threaded through Registration, uses the ForLt trait (a type-level abstraction for types generic over a lifetime). Misc: - Fix DT overlayed devices not probing by reverting the broken treewide overlay fix and re-running fw_devlink consumer pickup when an overlay is applied to a bound device - Use root_device_register() for faux bus root device; add sanity check for failed bus init - Fix dev_has_sync_state() data race with READ_ONCE() and move it to base.h - Avoid spurious device_links warning when removing a device while its supplier is unbinding - Switch ISA bus to dynamic root device - Fix suspicious RCU usage in kernfs_put() - Remove devcoredump exit callback - Constify devfreq_event_class" * tag 'driver-core-7.2-rc1' of gitolite.kernel.org:pub/scm/linux/kernel/git/driver-core/driver-core: (81 commits) software node: allow passing reference args to PROPERTY_ENTRY_REF() driver core: platform: set mod_name in driver registration coresight: pass THIS_MODULE implicitly through a macro kernel: param: initialize module_kset in a pure_initcall soc/tegra: cbb: Move driver registration from pure_initcall to core_initcall firmware_loader: Fix recursive lock in device_cache_fw_images() driver core: Use system_percpu_wq instead of system_wq driver core: remove driver_set_override() rpmsg: use generic driver_override infrastructure Drivers: hv: vmbus: use generic driver_override infrastructure cdx: use generic driver_override infrastructure amba: use generic driver_override infrastructure rust: devres: add 'static bound to Devres<T> samples: rust: rust_driver_auxiliary: showcase lifetime-bound registration data rust: auxiliary: generalize Registration over ForLt rust: types: add `ForLt` trait for higher-ranked lifetime support gpu: nova-core: separate driver type from driver data samples: rust: rust_driver_pci: use HRT lifetime for Bar rust: io: make IoMem and ExclusiveIoMem lifetime-parameterized rust: pci: make Bar lifetime-parameterized ...

Linus Torvalds committed 5 months ago

Commit 36808d52 parents 5504ce0 fe22174128 files · +1814 −1134Browse files

Unified · Split

128 files
  1. Documentation/admin-guide/kernel-parameters.txt +3 −2
  2. Documentation/driver-api/driver-model/platform.rst +2 −1
  3. MAINTAINERS +1 −0
  4. arch/arc/mm/dma.c +2 −2
  5. arch/arm/mach-highbank/highbank.c +1 −1
  6. arch/arm/mach-mvebu/coherency.c +1 −1
  7. arch/arm/mm/dma-mapping-nommu.c +2 −2
  8. arch/arm/mm/dma-mapping.c +14 −14
  9. arch/arm64/kernel/cpufeature.c +1 −1
  10. arch/arm64/mm/dma-mapping.c +1 −1
  11. arch/mips/include/asm/mips_mt.h +0 −1
  12. arch/mips/mm/dma-noncoherent.c +1 −1
  13. arch/powerpc/kernel/dma-iommu.c +4 −4
  14. arch/powerpc/platforms/pseries/hotplug-memory.c +2 −2
  15. arch/riscv/mm/dma-noncoherent.c +1 −1
  16. drivers/acpi/bus.c +3 −3
  17. drivers/acpi/scan.c +1 −1
  18. drivers/amba/bus.c +6 −31
  19. drivers/base/base.h +18 −18
  20. drivers/base/bus.c +9 −2
  21. drivers/base/core.c +125 −59
  22. drivers/base/cpu.c +2 −2
  23. drivers/base/dd.c +12 −15
  24. drivers/base/devcoredump.c +0 −7
  25. drivers/base/driver.c +2 −77
  26. drivers/base/faux.c +15 −17
  27. drivers/base/firmware_loader/main.c +2 −1
  28. drivers/base/firmware_loader/sysfs_upload.c +3 −5
  29. drivers/base/isa.c +6 −6
  30. drivers/base/memory.c +1 −1
  31. drivers/base/pinctrl.c +1 −1
  32. drivers/base/platform.c +15 −8
  33. drivers/base/property.c +3 −1
  34. drivers/base/swnode.c +24 −16
  35. drivers/bus/imx-weim.c +0 −6
  36. drivers/cdx/cdx.c +5 −35
  37. drivers/cpufreq/rcpufreq_dt.rs +5 −4
  38. drivers/devfreq/devfreq-event.c +13 −10
  39. drivers/dma/ti/k3-udma-glue.c +3 −3
  40. drivers/dma/ti/k3-udma.c +3 −3
  41. drivers/gpu/drm/nova/driver.rs +5 −1
  42. drivers/gpu/drm/tyr/driver.rs +7 −6
  43. drivers/gpu/nova-core/driver.rs +23 −15
  44. drivers/gpu/nova-core/gpu.rs +1 −1
  45. drivers/gpu/nova-core/nova_core.rs +1 −1
  46. drivers/hv/vmbus_drv.c +10 −33
  47. drivers/hwtracing/coresight/coresight-catu.c +1 −1
  48. drivers/hwtracing/coresight/coresight-core.c +5 −4
  49. drivers/hwtracing/coresight/coresight-cpu-debug.c +1 −2
  50. drivers/hwtracing/coresight/coresight-funnel.c +1 −2
  51. drivers/hwtracing/coresight/coresight-replicator.c +1 −2
  52. drivers/hwtracing/coresight/coresight-stm.c +1 −1
  53. drivers/hwtracing/coresight/coresight-tmc-core.c +1 −1
  54. drivers/hwtracing/coresight/coresight-tnoc.c +1 −1
  55. drivers/hwtracing/coresight/coresight-tpdm.c +1 −2
  56. drivers/hwtracing/coresight/coresight-tpiu.c +1 −1
  57. drivers/i2c/i2c-core-of.c +0 −5
  58. drivers/iommu/dma-iommu.c +6 −3
  59. drivers/iommu/iommu.c +2 −3
  60. drivers/net/pcs/pcs-xpcs-plat.c +1 −1
  61. drivers/of/device.c +3 −3
  62. drivers/of/dynamic.c +0 −1
  63. drivers/of/overlay.c +15 −0
  64. drivers/of/platform.c +0 −5
  65. drivers/pci/of.c +1 −1
  66. drivers/pci/pwrctrl/core.c +1 −1
  67. drivers/pwm/pwm_th1520.rs +7 −6
  68. drivers/rpmsg/qcom_glink_native.c +0 −2
  69. drivers/rpmsg/rpmsg_core.c +7 −36
  70. drivers/rpmsg/virtio_rpmsg_bus.c +0 −1
  71. drivers/soc/tegra/cbb/tegra194-cbb.c +1 −1
  72. drivers/soc/tegra/cbb/tegra234-cbb.c +1 −1
  73. drivers/spi/spi.c +0 −5
  74. drivers/tty/serial/serial_base_bus.c +1 −1
  75. drivers/usb/gadget/udc/aspeed-vhub/dev.c +1 −1
  76. fs/kernfs/dir.c +7 −4
  77. fs/sysfs/file.c +6 −3
  78. include/acpi/acpi_bus.h +11 −0
  79. include/linux/amba/bus.h +0 −5
  80. include/linux/auxiliary_bus.h +4 −0
  81. include/linux/cdx/cdx_bus.h +0 −4
  82. include/linux/coresight.h +5 −2
  83. include/linux/device.h +136 −85
  84. include/linux/device/bus.h +3 −3
  85. include/linux/device/class.h +1 −1
  86. include/linux/device/driver.h +4 −6
  87. include/linux/dma-map-ops.h +3 −3
  88. include/linux/dma-mapping.h +1 −1
  89. include/linux/fwnode.h +3 −0
  90. include/linux/hyperv.h +0 −5
  91. include/linux/iommu-dma.h +2 −1
  92. include/linux/platform_device.h +9 −8
  93. include/linux/property.h +7 −1
  94. include/linux/rpmsg.h +0 −4
  95. kernel/cpu.c +2 −2
  96. kernel/dma/mapping.c +5 −7
  97. kernel/params.c +4 −4
  98. mm/hmm.c +1 −1
  99. rust/Makefile +1 −0
  100. rust/helpers/acpi.c +16 −0
  101. rust/helpers/helpers.c +1 −0
  102. rust/kernel/alloc/kbox.rs +39 −6
  103. rust/kernel/auxiliary.rs +213 −72
  104. rust/kernel/cpufreq.rs +5 −4
  105. rust/kernel/device.rs +46 −75
  106. rust/kernel/devres.rs +4 −4
  107. rust/kernel/dma.rs +1 −1
  108. rust/kernel/driver.rs +88 −27
  109. rust/kernel/i2c.rs +34 −27
  110. rust/kernel/io/mem.rs +62 −59
  111. rust/kernel/pci.rs +31 −20
  112. rust/kernel/pci/id.rs +1 −1
  113. rust/kernel/pci/io.rs +31 −23
  114. rust/kernel/platform.rs +33 −23
  115. rust/kernel/types.rs +10 −2
  116. rust/kernel/types/for_lt.rs +122 −0
  117. rust/kernel/usb.rs +36 −21
  118. rust/macros/for_lt.rs +248 −0
  119. rust/macros/lib.rs +13 −0
  120. samples/rust/rust_debugfs.rs +6 −5
  121. samples/rust/rust_dma.rs +5 −1
  122. samples/rust/rust_driver_auxiliary.rs +56 −23
  123. samples/rust/rust_driver_i2c.rs +7 −6
  124. samples/rust/rust_driver_pci.rs +43 −47
  125. samples/rust/rust_driver_platform.rs +5 −4
  126. samples/rust/rust_driver_usb.rs +8 −7
  127. samples/rust/rust_i2c_client.rs +9 −5
  128. samples/rust/rust_soc.rs +5 −4
Documentation/admin-guide/kernel-parameters.txt+3−2
@@ -1228,8 +1228,9 @@ Kernel parameters · 1227 unmodified lines
1228 deferred probe to give up waiting on dependencies to1228 deferred probe to give up waiting on dependencies to
1229 probe. Only specific dependencies (subsystems or1229 probe. Only specific dependencies (subsystems or
1230 drivers) that have opted in will be ignored. A timeout1230 drivers) that have opted in will be ignored. A timeout
1231 of 0 will timeout at the end of initcalls. If the time1231 of 0 will timeout at the end of initcalls; a negative
1232 out hasn't expired, it'll be restarted by each1232 value is treated as an infinite timeout value. If the
1233 timeout hasn't expired, it'll be restarted by each
1233 successful driver registration. This option will also1234 successful driver registration. This option will also
1234 dump out devices still on the deferred probe list after1235 dump out devices still on the deferred probe list after
1235 retrying.1236 retrying.
Documentation/driver-api/driver-model/platform.rst+2−1
@@ -70,7 +70,8 @@ Kernel modules can be composed of several platform drivers. The platform core · 69 unmodified lines
70provides helpers to register and unregister an array of drivers::70provides helpers to register and unregister an array of drivers::
71 71
72 int __platform_register_drivers(struct platform_driver * const *drivers,72 int __platform_register_drivers(struct platform_driver * const *drivers,
73 unsigned int count, struct module *owner);73 unsigned int count, struct module *owner,
74 const char *mod_name);
74 void platform_unregister_drivers(struct platform_driver * const *drivers,75 void platform_unregister_drivers(struct platform_driver * const *drivers,
75 unsigned int count);76 unsigned int count);
76 77
MAINTAINERS+1−0
@@ -297,6 +297,7 @@ F: include/linux/acpi.h · 296 unmodified lines
297F: include/linux/fwnode.h297F: include/linux/fwnode.h
298F: include/linux/fw_table.h298F: include/linux/fw_table.h
299F: lib/fw_table.c299F: lib/fw_table.c
300F: rust/helpers/acpi.c
300F: rust/kernel/acpi.rs301F: rust/kernel/acpi.rs
301F: tools/power/acpi/302F: tools/power/acpi/
302 303
arch/arc/mm/dma.c+2−2
@@ -98,8 +98,8 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) · 97 unmodified lines
98 * DMA buffers.98 * DMA buffers.
99 */99 */
100 if (is_isa_arcv2() && ioc_enable && coherent)100 if (is_isa_arcv2() && ioc_enable && coherent)
101 dev->dma_coherent = true;101 dev_set_dma_coherent(dev);
102 102
103 dev_info(dev, "use %scoherent DMA ops\n",103 dev_info(dev, "use %scoherent DMA ops\n",
104 dev->dma_coherent ? "" : "non");104 dev_dma_coherent(dev) ? "" : "non");
105}105}
arch/arm/mach-highbank/highbank.c+1−1
@@ -98,7 +98,7 @@ static int highbank_platform_notifier(struct notifier_block *nb, · 97 unmodified lines
98 if (of_property_read_bool(dev->of_node, "dma-coherent")) {98 if (of_property_read_bool(dev->of_node, "dma-coherent")) {
99 val = readl(sregs_base + reg);99 val = readl(sregs_base + reg);
100 writel(val | 0xff01, sregs_base + reg);100 writel(val | 0xff01, sregs_base + reg);
101 dev->dma_coherent = true;101 dev_set_dma_coherent(dev);
102 }102 }
103 103
104 return NOTIFY_OK;104 return NOTIFY_OK;
arch/arm/mach-mvebu/coherency.c+1−1
@@ -95,7 +95,7 @@ static int mvebu_hwcc_notifier(struct notifier_block *nb, · 94 unmodified lines
95 95
96 if (event != BUS_NOTIFY_ADD_DEVICE)96 if (event != BUS_NOTIFY_ADD_DEVICE)
97 return NOTIFY_DONE;97 return NOTIFY_DONE;
98 dev->dma_coherent = true;98 dev_set_dma_coherent(dev);
99 99
100 return NOTIFY_OK;100 return NOTIFY_OK;
101}101}
arch/arm/mm/dma-mapping-nommu.c+2−2
@@ -42,11 +42,11 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) · 41 unmodified lines
42 * enough to check if MPU is in use or not since in absence of42 * enough to check if MPU is in use or not since in absence of
43 * MPU system memory map is used.43 * MPU system memory map is used.
44 */44 */
45 dev->dma_coherent = cacheid ? coherent : true;45 dev_assign_dma_coherent(dev, cacheid ? coherent : true);
46 } else {46 } else {
47 /*47 /*
48 * Assume coherent DMA in case MMU/MPU has not been set up.48 * Assume coherent DMA in case MMU/MPU has not been set up.
49 */49 */
50 dev->dma_coherent = (get_cr() & CR_M) ? coherent : true;50 dev_assign_dma_coherent(dev, (get_cr() & CR_M) ? coherent : true);
51 }51 }
52}52}
arch/arm/mm/dma-mapping.c+14−14
@@ -1076,7 +1076,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, · 1075 unmodified lines
1076 pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);1076 pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
1077 struct page **pages;1077 struct page **pages;
1078 void *addr = NULL;1078 void *addr = NULL;
1079 int coherent_flag = dev->dma_coherent ? COHERENT : NORMAL;1079 int coherent_flag = dev_dma_coherent(dev) ? COHERENT : NORMAL;
1080 1080
1081 *handle = DMA_MAPPING_ERROR;1081 *handle = DMA_MAPPING_ERROR;
1082 size = PAGE_ALIGN(size);1082 size = PAGE_ALIGN(size);
@@ -1124,7 +1124,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, · 41 unmodified lines
1124 if (vma->vm_pgoff >= nr_pages)1124 if (vma->vm_pgoff >= nr_pages)
1125 return -ENXIO;1125 return -ENXIO;
1126 1126
1127 if (!dev->dma_coherent)1127 if (!dev_dma_coherent(dev))
1128 vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);1128 vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
1129 1129
1130 err = vm_map_pages(vma, pages, nr_pages);1130 err = vm_map_pages(vma, pages, nr_pages);
@@ -1141,7 +1141,7 @@ static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma, · 10 unmodified lines
1141static void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,1141static void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
1142 dma_addr_t handle, unsigned long attrs)1142 dma_addr_t handle, unsigned long attrs)
1143{1143{
1144 int coherent_flag = dev->dma_coherent ? COHERENT : NORMAL;1144 int coherent_flag = dev_dma_coherent(dev) ? COHERENT : NORMAL;
1145 struct page **pages;1145 struct page **pages;
1146 size = PAGE_ALIGN(size);1146 size = PAGE_ALIGN(size);
1147 1147
@@ -1202,7 +1202,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg, · 54 unmodified lines
1202 phys_addr_t phys = page_to_phys(sg_page(s));1202 phys_addr_t phys = page_to_phys(sg_page(s));
1203 unsigned int len = PAGE_ALIGN(s->offset + s->length);1203 unsigned int len = PAGE_ALIGN(s->offset + s->length);
1204 1204
1205 if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))1205 if (!dev_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
1206 arch_sync_dma_for_device(sg_phys(s), s->length, dir);1206 arch_sync_dma_for_device(sg_phys(s), s->length, dir);
1207 1207
1208 prot = __dma_info_to_prot(dir, attrs);1208 prot = __dma_info_to_prot(dir, attrs);
@@ -1304,7 +1304,7 @@ static void arm_iommu_unmap_sg(struct device *dev, · 95 unmodified lines
1304 if (sg_dma_len(s))1304 if (sg_dma_len(s))
1305 __iommu_remove_mapping(dev, sg_dma_address(s),1305 __iommu_remove_mapping(dev, sg_dma_address(s),
1306 sg_dma_len(s));1306 sg_dma_len(s));
1307 if (!dev->dma_coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))1307 if (!dev_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
1308 arch_sync_dma_for_cpu(sg_phys(s), s->length, dir);1308 arch_sync_dma_for_cpu(sg_phys(s), s->length, dir);
1309 }1309 }
1310}1310}
@@ -1323,7 +1323,7 @@ static void arm_iommu_sync_sg_for_cpu(struct device *dev, · 12 unmodified lines
1323 struct scatterlist *s;1323 struct scatterlist *s;
1324 int i;1324 int i;
1325 1325
1326 if (dev->dma_coherent)1326 if (dev_dma_coherent(dev))
1327 return;1327 return;
1328 1328
1329 for_each_sg(sg, s, nents, i)1329 for_each_sg(sg, s, nents, i)
@@ -1345,7 +1345,7 @@ static void arm_iommu_sync_sg_for_device(struct device *dev, · 15 unmodified lines
1345 struct scatterlist *s;1345 struct scatterlist *s;
1346 int i;1346 int i;
1347 1347
1348 if (dev->dma_coherent)1348 if (dev_dma_coherent(dev))
1349 return;1349 return;
1350 1350
1351 for_each_sg(sg, s, nents, i)1351 for_each_sg(sg, s, nents, i)
@@ -1371,7 +1371,7 @@ static dma_addr_t arm_iommu_map_phys(struct device *dev, phys_addr_t phys, · 19 unmodified lines
1371 dma_addr_t dma_addr;1371 dma_addr_t dma_addr;
1372 int ret, prot;1372 int ret, prot;
1373 1373
1374 if (!dev->dma_coherent &&1374 if (!dev_dma_coherent(dev) &&
1375 !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO)))1375 !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO)))
1376 arch_sync_dma_for_device(phys, size, dir);1376 arch_sync_dma_for_device(phys, size, dir);
1377 1377
@@ -1412,7 +1412,7 @@ static void arm_iommu_unmap_phys(struct device *dev, dma_addr_t handle, · 34 unmodified lines
1412 if (!iova)1412 if (!iova)
1413 return;1413 return;
1414 1414
1415 if (!dev->dma_coherent &&1415 if (!dev_dma_coherent(dev) &&
1416 !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) {1416 !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) {
1417 phys_addr_t phys = iommu_iova_to_phys(mapping->domain, iova);1417 phys_addr_t phys = iommu_iova_to_phys(mapping->domain, iova);
1418 1418
@@ -1431,7 +1431,7 @@ static void arm_iommu_sync_single_for_cpu(struct device *dev, · 12 unmodified lines
1431 unsigned int offset = handle & ~PAGE_MASK;1431 unsigned int offset = handle & ~PAGE_MASK;
1432 phys_addr_t phys;1432 phys_addr_t phys;
1433 1433
1434 if (dev->dma_coherent || !iova)1434 if (dev_dma_coherent(dev) || !iova)
1435 return;1435 return;
1436 1436
1437 phys = iommu_iova_to_phys(mapping->domain, iova);1437 phys = iommu_iova_to_phys(mapping->domain, iova);
@@ -1446,7 +1446,7 @@ static void arm_iommu_sync_single_for_device(struct device *dev, · 8 unmodified lines
1446 unsigned int offset = handle & ~PAGE_MASK;1446 unsigned int offset = handle & ~PAGE_MASK;
1447 phys_addr_t phys;1447 phys_addr_t phys;
1448 1448
1449 if (dev->dma_coherent || !iova)1449 if (dev_dma_coherent(dev) || !iova)
1450 return;1450 return;
1451 1451
1452 phys = iommu_iova_to_phys(mapping->domain, iova);1452 phys = iommu_iova_to_phys(mapping->domain, iova);
@@ -1701,13 +1701,13 @@ static void arm_teardown_iommu_dma_ops(struct device *dev) { } · 248 unmodified lines
1701void arch_setup_dma_ops(struct device *dev, bool coherent)1701void arch_setup_dma_ops(struct device *dev, bool coherent)
1702{1702{
1703 /*1703 /*
1704 * Due to legacy code that sets the ->dma_coherent flag from a bus1704 * Due to legacy code that sets the dma_coherent flag from a bus
1705 * notifier we can't just assign coherent to the ->dma_coherent flag1705 * notifier we can't just assign coherent to the dma_coherent flag
1706 * here, but instead have to make sure we only set but never clear it1706 * here, but instead have to make sure we only set but never clear it
1707 * for now.1707 * for now.
1708 */1708 */
1709 if (coherent)1709 if (coherent)
1710 dev->dma_coherent = true;1710 dev_set_dma_coherent(dev);
1711 1711
1712 /*1712 /*
1713 * Don't override the dma_ops if they have already been set. Ideally1713 * Don't override the dma_ops if they have already been set. Ideally
arch/arm64/kernel/cpufeature.c+1−1
@@ -4052,7 +4052,7 @@ static int enable_mismatched_32bit_el0(unsigned int cpu) · 4051 unmodified lines
4052 */4052 */
4053 lucky_winner = cpu_32bit ? cpu : cpumask_any_and(cpu_32bit_el0_mask,4053 lucky_winner = cpu_32bit ? cpu : cpumask_any_and(cpu_32bit_el0_mask,
4054 cpu_active_mask);4054 cpu_active_mask);
4055 get_cpu_device(lucky_winner)->offline_disabled = true;4055 dev_set_offline_disabled(get_cpu_device(lucky_winner));
4056 setup_elf_hwcaps(compat_elf_hwcaps);4056 setup_elf_hwcaps(compat_elf_hwcaps);
4057 elf_hwcap_fixup();4057 elf_hwcap_fixup();
4058 pr_info("Asymmetric 32-bit EL0 support detected on CPU %u; CPU hot-unplug disabled on CPU %u\n",4058 pr_info("Asymmetric 32-bit EL0 support detected on CPU %u; CPU hot-unplug disabled on CPU %u\n",
arch/arm64/mm/dma-mapping.c+1−1
@@ -48,7 +48,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) · 47 unmodified lines
48 dev_driver_string(dev), dev_name(dev),48 dev_driver_string(dev), dev_name(dev),
49 ARCH_DMA_MINALIGN, cls);49 ARCH_DMA_MINALIGN, cls);
50 50
51 dev->dma_coherent = coherent;51 dev_assign_dma_coherent(dev, coherent);
52 52
53 xen_setup_dma_ops(dev);53 xen_setup_dma_ops(dev);
54}54}
arch/mips/include/asm/mips_mt.h+0−1
@@ -23,7 +23,6 @@ extern void mips_mt_set_cpuoptions(void); · 22 unmodified lines
23static inline void mips_mt_set_cpuoptions(void) { }23static inline void mips_mt_set_cpuoptions(void) { }
24#endif24#endif
25 25
26struct class;
27extern const struct class mt_class;26extern const struct class mt_class;
28 27
29#endif /* __ASM_MIPS_MT_H */28#endif /* __ASM_MIPS_MT_H */
arch/mips/mm/dma-noncoherent.c+1−1
@@ -139,6 +139,6 @@ void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, · 138 unmodified lines
139#ifdef CONFIG_ARCH_HAS_SETUP_DMA_OPS139#ifdef CONFIG_ARCH_HAS_SETUP_DMA_OPS
140void arch_setup_dma_ops(struct device *dev, bool coherent)140void arch_setup_dma_ops(struct device *dev, bool coherent)
141{141{
142 dev->dma_coherent = coherent;142 dev_assign_dma_coherent(dev, coherent);
143}143}
144#endif144#endif
arch/powerpc/kernel/dma-iommu.c+4−4
@@ -67,7 +67,7 @@ bool arch_dma_unmap_sg_direct(struct device *dev, struct scatterlist *sg, · 66 unmodified lines
67}67}
68bool arch_dma_alloc_direct(struct device *dev)68bool arch_dma_alloc_direct(struct device *dev)
69{69{
70 if (dev->dma_ops_bypass && dev->bus_dma_limit)70 if (dev_dma_ops_bypass(dev) && dev->bus_dma_limit)
71 return true;71 return true;
72 72
73 return false;73 return false;
@@ -75,7 +75,7 @@ bool arch_dma_alloc_direct(struct device *dev) · 1 unmodified line
75 75
76bool arch_dma_free_direct(struct device *dev, dma_addr_t dma_handle)76bool arch_dma_free_direct(struct device *dev, dma_addr_t dma_handle)
77{77{
78 if (!dev->dma_ops_bypass || !dev->bus_dma_limit)78 if (!dev_dma_ops_bypass(dev) || !dev->bus_dma_limit)
79 return false;79 return false;
80 80
81 return is_direct_handle(dev, dma_handle);81 return is_direct_handle(dev, dma_handle);
@@ -164,7 +164,7 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask) · 82 unmodified lines
164 * fixed ops will be used for RAM. This is limited by164 * fixed ops will be used for RAM. This is limited by
165 * bus_dma_limit which is set when RAM is pre-mapped.165 * bus_dma_limit which is set when RAM is pre-mapped.
166 */166 */
167 dev->dma_ops_bypass = true;167 dev_set_dma_ops_bypass(dev);
168 dev_info(dev, "iommu: 64-bit OK but direct DMA is limited by %llx\n",168 dev_info(dev, "iommu: 64-bit OK but direct DMA is limited by %llx\n",
169 dev->bus_dma_limit);169 dev->bus_dma_limit);
170 return 1;170 return 1;
@@ -185,7 +185,7 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask) · 14 unmodified lines
185 }185 }
186 186
187 dev_dbg(dev, "iommu: not 64-bit, using default ops\n");187 dev_dbg(dev, "iommu: not 64-bit, using default ops\n");
188 dev->dma_ops_bypass = false;188 dev_clear_dma_ops_bypass(dev);
189 return 1;189 return 1;
190}190}
191 191
arch/powerpc/platforms/pseries/hotplug-memory.c+2−2
@@ -213,9 +213,9 @@ static int dlpar_change_lmb_state(struct drmem_lmb *lmb, bool online) · 212 unmodified lines
213 return -EINVAL;213 return -EINVAL;
214 }214 }
215 215
216 if (online && mem_block->dev.offline)216 if (online && dev_offline(&mem_block->dev))
217 rc = device_online(&mem_block->dev);217 rc = device_online(&mem_block->dev);
218 else if (!online && !mem_block->dev.offline)218 else if (!online && !dev_offline(&mem_block->dev))
219 rc = device_offline(&mem_block->dev);219 rc = device_offline(&mem_block->dev);
220 else220 else
221 rc = 0;221 rc = 0;
arch/riscv/mm/dma-noncoherent.c+1−1
@@ -140,7 +140,7 @@ void arch_setup_dma_ops(struct device *dev, bool coherent) · 139 unmodified lines
140 "%s %s: device non-coherent but no non-coherent operations supported",140 "%s %s: device non-coherent but no non-coherent operations supported",
141 dev_driver_string(dev), dev_name(dev));141 dev_driver_string(dev), dev_name(dev));
142 142
143 dev->dma_coherent = coherent;143 dev_assign_dma_coherent(dev, coherent);
144}144}
145 145
146void riscv_noncoherent_supported(void)146void riscv_noncoherent_supported(void)
drivers/acpi/bus.c+3−3
@@ -898,9 +898,9 @@ const struct acpi_device *acpi_companion_match(const struct device *dev) · 897 unmodified lines
898 * identifiers and a _DSD object with the "compatible" property, use that898 * identifiers and a _DSD object with the "compatible" property, use that
899 * property to match against the given list of identifiers.899 * property to match against the given list of identifiers.
900 */900 */
901static bool acpi_of_match_device(const struct acpi_device *adev,901bool acpi_of_match_device(const struct acpi_device *adev,
902 const struct of_device_id *of_match_table,902 const struct of_device_id *of_match_table,
903 const struct of_device_id **of_id)903 const struct of_device_id **of_id)
904{904{
905 const union acpi_object *of_compatible, *obj;905 const union acpi_object *of_compatible, *obj;
906 int i, nval;906 int i, nval;
drivers/acpi/scan.c+1−1
@@ -122,7 +122,7 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent) · 121 unmodified lines
122 mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING);122 mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING);
123 123
124 list_for_each_entry(pn, &adev->physical_node_list, node)124 list_for_each_entry(pn, &adev->physical_node_list, node)
125 if (device_supports_offline(pn->dev) && !pn->dev->offline) {125 if (device_supports_offline(pn->dev) && !dev_offline(pn->dev)) {
126 if (uevent)126 if (uevent)
127 kobject_uevent_env(&pn->dev->kobj, KOBJ_CHANGE, envp);127 kobject_uevent_env(&pn->dev->kobj, KOBJ_CHANGE, envp);
128 128
drivers/amba/bus.c+6−31
@@ -82,33 +82,6 @@ static void amba_put_disable_pclk(struct amba_device *pcdev) · 81 unmodified lines
82}82}
83 83
84 84
85static ssize_t driver_override_show(struct device *_dev,
86 struct device_attribute *attr, char *buf)
87{
88 struct amba_device *dev = to_amba_device(_dev);
89 ssize_t len;
90
91 device_lock(_dev);
92 len = sprintf(buf, "%s\n", dev->driver_override);
93 device_unlock(_dev);
94 return len;
95}
96
97static ssize_t driver_override_store(struct device *_dev,
98 struct device_attribute *attr,
99 const char *buf, size_t count)
100{
101 struct amba_device *dev = to_amba_device(_dev);
102 int ret;
103
104 ret = driver_set_override(_dev, &dev->driver_override, buf, count);
105 if (ret)
106 return ret;
107
108 return count;
109}
110static DEVICE_ATTR_RW(driver_override);
111
112#define amba_attr_func(name,fmt,arg...) \85#define amba_attr_func(name,fmt,arg...) \
113static ssize_t name##_show(struct device *_dev, \86static ssize_t name##_show(struct device *_dev, \
114 struct device_attribute *attr, char *buf) \87 struct device_attribute *attr, char *buf) \
@@ -126,7 +99,6 @@ amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n", · 11 unmodified lines
126static struct attribute *amba_dev_attrs[] = {99static struct attribute *amba_dev_attrs[] = {
127 &dev_attr_id.attr,100 &dev_attr_id.attr,
128 &dev_attr_resource.attr,101 &dev_attr_resource.attr,
129 &dev_attr_driver_override.attr,
130 NULL,102 NULL,
131};103};
132ATTRIBUTE_GROUPS(amba_dev);104ATTRIBUTE_GROUPS(amba_dev);
@@ -209,10 +181,11 @@ static int amba_match(struct device *dev, const struct device_driver *drv) · 76 unmodified lines
209{181{
210 struct amba_device *pcdev = to_amba_device(dev);182 struct amba_device *pcdev = to_amba_device(dev);
211 const struct amba_driver *pcdrv = to_amba_driver(drv);183 const struct amba_driver *pcdrv = to_amba_driver(drv);
184 int ret;
212 185
213 mutex_lock(&pcdev->periphid_lock);186 mutex_lock(&pcdev->periphid_lock);
214 if (!pcdev->periphid) {187 if (!pcdev->periphid) {
215 int ret = amba_read_periphid(pcdev);188 ret = amba_read_periphid(pcdev);
216 189
217 /*190 /*
218 * Returning any error other than -EPROBE_DEFER from bus match191 * Returning any error other than -EPROBE_DEFER from bus match
@@ -230,8 +203,9 @@ static int amba_match(struct device *dev, const struct device_driver *drv) · 11 unmodified lines
230 mutex_unlock(&pcdev->periphid_lock);203 mutex_unlock(&pcdev->periphid_lock);
231 204
232 /* When driver_override is set, only bind to the matching driver */205 /* When driver_override is set, only bind to the matching driver */
233 if (pcdev->driver_override)206 ret = device_match_driver_override(dev, drv);
234 return !strcmp(pcdev->driver_override, drv->name);207 if (ret >= 0)
208 return ret;
235 209
236 return amba_lookup(pcdrv->id_table, pcdev) != NULL;210 return amba_lookup(pcdrv->id_table, pcdev) != NULL;
237}211}
@@ -436,6 +410,7 @@ static const struct dev_pm_ops amba_pm = { · 198 unmodified lines
436const struct bus_type amba_bustype = {410const struct bus_type amba_bustype = {
437 .name = "amba",411 .name = "amba",
438 .dev_groups = amba_dev_groups,412 .dev_groups = amba_dev_groups,
413 .driver_override = true,
439 .match = amba_match,414 .match = amba_match,
440 .uevent = amba_uevent,415 .uevent = amba_uevent,
441 .probe = amba_probe,416 .probe = amba_probe,
drivers/base/base.h+18−18
@@ -86,18 +86,6 @@ struct driver_private { · 85 unmodified lines
86};86};
87#define to_driver(obj) container_of(obj, struct driver_private, kobj)87#define to_driver(obj) container_of(obj, struct driver_private, kobj)
88 88
89#ifdef CONFIG_RUST
90/**
91 * struct driver_type - Representation of a Rust driver type.
92 */
93struct driver_type {
94 /**
95 * @id: Representation of core::any::TypeId.
96 */
97 u8 id[16];
98} __packed;
99#endif
100
101/**89/**
102 * struct device_private - structure to hold the private to the driver core90 * struct device_private - structure to hold the private to the driver core
103 * portions of the device structure.91 * portions of the device structure.
@@ -115,7 +103,6 @@ struct driver_type { · 11 unmodified lines
115 * dev_err_probe() for later retrieval via debugfs103 * dev_err_probe() for later retrieval via debugfs
116 * @device: pointer back to the struct device that this structure is104 * @device: pointer back to the struct device that this structure is
117 * associated with.105 * associated with.
118 * @driver_type: The type of the bound Rust driver.
119 * @dead: This device is currently either in the process of or has been106 * @dead: This device is currently either in the process of or has been
120 * removed from the system. Any asynchronous events scheduled for this107 * removed from the system. Any asynchronous events scheduled for this
121 * device should exit without taking any action.108 * device should exit without taking any action.
@@ -132,9 +119,6 @@ struct device_private { · 10 unmodified lines
132 const struct device_driver *async_driver;119 const struct device_driver *async_driver;
133 char *deferred_probe_reason;120 char *deferred_probe_reason;
134 struct device *device;121 struct device *device;
135#ifdef CONFIG_RUST
136 struct driver_type driver_type;
137#endif
138 u8 dead:1;122 u8 dead:1;
139};123};
140#define to_device_private_parent(obj) \124#define to_device_private_parent(obj) \
@@ -188,6 +172,20 @@ static inline int driver_match_device(const struct device_driver *drv, · 47 unmodified lines
188 return drv->bus->match ? drv->bus->match(dev, drv) : 1;172 return drv->bus->match ? drv->bus->match(dev, drv) : 1;
189}173}
190 174
175static inline bool dev_has_sync_state(struct device *dev)
176{
177 struct device_driver *drv;
178
179 if (!dev)
180 return false;
181 drv = READ_ONCE(dev->driver);
182 if (drv && drv->sync_state)
183 return true;
184 if (dev->bus && dev->bus->sync_state)
185 return true;
186 return false;
187}
188
191static inline void dev_sync_state(struct device *dev)189static inline void dev_sync_state(struct device *dev)
192{190{
193 if (dev->bus->sync_state)191 if (dev->bus->sync_state)
@@ -196,8 +194,10 @@ static inline void dev_sync_state(struct device *dev) · 2 unmodified lines
196 dev->driver->sync_state(dev);194 dev->driver->sync_state(dev);
197}195}
198 196
199int driver_add_groups(const struct device_driver *drv, const struct attribute_group **groups);197int driver_add_groups(const struct device_driver *drv,
200void driver_remove_groups(const struct device_driver *drv, const struct attribute_group **groups);198 const struct attribute_group *const *groups);
199void driver_remove_groups(const struct device_driver *drv,
200 const struct attribute_group *const *groups);
201void device_driver_detach(struct device *dev);201void device_driver_detach(struct device *dev);
202 202
203static inline void device_set_driver(struct device *dev, const struct device_driver *drv)203static inline void device_set_driver(struct device *dev, const struct device_driver *drv)
drivers/base/bus.c+9−2
@@ -544,10 +544,10 @@ static const struct attribute_group driver_override_dev_group = { · 543 unmodified lines
544 */544 */
545int bus_add_device(struct device *dev)545int bus_add_device(struct device *dev)
546{546{
547 struct subsys_private *sp = bus_to_subsys(dev->bus);547 struct subsys_private *sp;
548 int error;548 int error;
549 549
550 if (!sp) {550 if (!dev->bus) {
551 /*551 /*
552 * This is a normal operation for many devices that do not552 * This is a normal operation for many devices that do not
553 * have a bus assigned to them, just say that all went553 * have a bus assigned to them, just say that all went
@@ -556,6 +556,13 @@ int bus_add_device(struct device *dev) · 2 unmodified lines
556 return 0;556 return 0;
557 }557 }
558 558
559 sp = bus_to_subsys(dev->bus);
560 if (!sp) {
561 pr_err("%s: cannot add device '%s' to unregistered bus '%s'\n",
562 __func__, dev_name(dev), dev->bus->name);
563 return -EINVAL;
564 }
565
559 /*566 /*
560 * Reference in sp is now incremented and will be dropped when567 * Reference in sp is now incremented and will be dropped when
561 * the device is removed from the bus568 * the device is removed from the bus
drivers/base/core.c+125−59
@@ -235,6 +235,79 @@ static void __fw_devlink_pickup_dangling_consumers(struct fwnode_handle *fwnode, · 234 unmodified lines
235 __fw_devlink_pickup_dangling_consumers(child, new_sup);235 __fw_devlink_pickup_dangling_consumers(child, new_sup);
236}236}
237 237
238static void fw_devlink_pickup_dangling_consumers(struct device *dev)
239{
240 struct fwnode_handle *child;
241
242 guard(mutex)(&fwnode_link_lock);
243
244 fwnode_for_each_available_child_node(dev->fwnode, child)
245 __fw_devlink_pickup_dangling_consumers(child, dev->fwnode);
246 __fw_devlink_link_to_consumers(dev);
247}
248
249/**
250 * fw_devlink_refresh_fwnode - Recheck the tree under this firmware node
251 * @fwnode: The fwnode under which the fwnode tree has changed
252 *
253 * This function is mainly meant to adjust the supplier/consumer dependencies
254 * after a fwnode tree overlay has occurred.
255 */
256void fw_devlink_refresh_fwnode(struct fwnode_handle *fwnode)
257{
258 struct device *dev;
259
260 /*
261 * Find the closest ancestor fwnode that has been converted to a device
262 * that can bind to a driver (bus device).
263 */
264 fwnode_handle_get(fwnode);
265 do {
266 if (fwnode_test_flag(fwnode, FWNODE_FLAG_NOT_DEVICE))
267 continue;
268
269 dev = get_dev_from_fwnode(fwnode);
270 if (!dev)
271 continue;
272
273 if (dev->bus)
274 break;
275
276 put_device(dev);
277 } while ((fwnode = fwnode_get_next_parent(fwnode)));
278
279 /*
280 * If none of the ancestor fwnodes have (yet) been converted to a device
281 * that can bind to a driver, there's nothing to fix up.
282 */
283 if (!fwnode)
284 return;
285
286 WARN(device_is_bound(dev) && dev->links.status != DL_DEV_DRIVER_BOUND,
287 "Don't multithread overlaying and probing the same device!\n");
288
289 /*
290 * If the device has already bound to a driver, then we need to redo
291 * some of the work that was done after the device was bound to a
292 * driver. If the device hasn't bound to a driver, running things too
293 * soon would incorrectly pick up consumers that it shouldn't.
294 */
295 if (dev->links.status == DL_DEV_DRIVER_BOUND) {
296 fw_devlink_pickup_dangling_consumers(dev);
297 /*
298 * Some of dangling consumers could have been put previously in
299 * the deferred probe list due to the unavailability of their
300 * suppliers. Those consumers have been picked up and some of
301 * their suppliers links have been updated. Time to re-try their
302 * probe sequence.
303 */
304 driver_deferred_probe_trigger();
305 }
306
307 put_device(dev);
308 fwnode_handle_put(fwnode);
309}
310
238static DEFINE_MUTEX(device_links_lock);311static DEFINE_MUTEX(device_links_lock);
239DEFINE_STATIC_SRCU(device_links_srcu);312DEFINE_STATIC_SRCU(device_links_srcu);
240 313
@@ -422,7 +495,7 @@ void device_pm_move_to_tail(struct device *dev) · 181 unmodified lines
422#define to_devlink(dev) container_of((dev), struct device_link, link_dev)495#define to_devlink(dev) container_of((dev), struct device_link, link_dev)
423 496
424static ssize_t status_show(struct device *dev,497static ssize_t status_show(struct device *dev,
425 struct device_attribute *attr, char *buf)498 const struct device_attribute *attr, char *buf)
426{499{
427 const char *output;500 const char *output;
428 501
@@ -452,10 +525,10 @@ static ssize_t status_show(struct device *dev, · 23 unmodified lines
452 525
453 return sysfs_emit(buf, "%s\n", output);526 return sysfs_emit(buf, "%s\n", output);
454}527}
455static DEVICE_ATTR_RO(status);528static const DEVICE_ATTR_RO(status);
456 529
457static ssize_t auto_remove_on_show(struct device *dev,530static ssize_t auto_remove_on_show(struct device *dev,
458 struct device_attribute *attr, char *buf)531 const struct device_attribute *attr, char *buf)
459{532{
460 struct device_link *link = to_devlink(dev);533 struct device_link *link = to_devlink(dev);
461 const char *output;534 const char *output;
@@ -469,27 +542,27 @@ static ssize_t auto_remove_on_show(struct device *dev, · 7 unmodified lines
469 542
470 return sysfs_emit(buf, "%s\n", output);543 return sysfs_emit(buf, "%s\n", output);
471}544}
472static DEVICE_ATTR_RO(auto_remove_on);545static const DEVICE_ATTR_RO(auto_remove_on);
473 546
474static ssize_t runtime_pm_show(struct device *dev,547static ssize_t runtime_pm_show(struct device *dev,
475 struct device_attribute *attr, char *buf)548 const struct device_attribute *attr, char *buf)
476{549{
477 struct device_link *link = to_devlink(dev);550 struct device_link *link = to_devlink(dev);
478 551
479 return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_PM_RUNTIME));552 return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_PM_RUNTIME));
480}553}
481static DEVICE_ATTR_RO(runtime_pm);554static const DEVICE_ATTR_RO(runtime_pm);
482 555
483static ssize_t sync_state_only_show(struct device *dev,556static ssize_t sync_state_only_show(struct device *dev,
484 struct device_attribute *attr, char *buf)557 const struct device_attribute *attr, char *buf)
485{558{
486 struct device_link *link = to_devlink(dev);559 struct device_link *link = to_devlink(dev);
487 560
488 return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));561 return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
489}562}
490static DEVICE_ATTR_RO(sync_state_only);563static const DEVICE_ATTR_RO(sync_state_only);
491 564
492static struct attribute *devlink_attrs[] = {565static const struct attribute *const devlink_attrs[] = {
493 &dev_attr_status.attr,566 &dev_attr_status.attr,
494 &dev_attr_auto_remove_on.attr,567 &dev_attr_auto_remove_on.attr,
495 &dev_attr_runtime_pm.attr,568 &dev_attr_runtime_pm.attr,
@@ -1011,7 +1084,7 @@ static void device_links_missing_supplier(struct device *dev) · 515 unmodified lines
1011 1084
1012static bool dev_is_best_effort(struct device *dev)1085static bool dev_is_best_effort(struct device *dev)
1013{1086{
1014 return (fw_devlink_best_effort && dev->can_match) ||1087 return (fw_devlink_best_effort && dev_can_match(dev)) ||
1015 (dev->fwnode && fwnode_test_flag(dev->fwnode, FWNODE_FLAG_BEST_EFFORT));1088 (dev->fwnode && fwnode_test_flag(dev->fwnode, FWNODE_FLAG_BEST_EFFORT));
1016}1089}
1017 1090
@@ -1079,7 +1152,7 @@ int device_links_check_suppliers(struct device *dev) · 61 unmodified lines
1079 1152
1080 if (dev_is_best_effort(dev) &&1153 if (dev_is_best_effort(dev) &&
1081 device_link_test(link, DL_FLAG_INFERRED) &&1154 device_link_test(link, DL_FLAG_INFERRED) &&
1082 !link->supplier->can_match) {1155 !dev_can_match(link->supplier)) {
1083 ret = -EAGAIN;1156 ret = -EAGAIN;
1084 continue;1157 continue;
1085 }1158 }
@@ -1123,7 +1196,7 @@ static void __device_links_queue_sync_state(struct device *dev, · 37 unmodified lines
1123 1196
1124 if (!dev_has_sync_state(dev))1197 if (!dev_has_sync_state(dev))
1125 return;1198 return;
1126 if (dev->state_synced)1199 if (dev_state_synced(dev))
1127 return;1200 return;
1128 1201
1129 list_for_each_entry(link, &dev->links.consumers, s_node) {1202 list_for_each_entry(link, &dev->links.consumers, s_node) {
@@ -1138,7 +1211,7 @@ static void __device_links_queue_sync_state(struct device *dev, · 8 unmodified lines
1138 * than once. This can happen if new consumers get added to the device1211 * than once. This can happen if new consumers get added to the device
1139 * and probed before the list is flushed.1212 * and probed before the list is flushed.
1140 */1213 */
1141 dev->state_synced = true;1214 dev_set_state_synced(dev);
1142 1215
1143 if (WARN_ON(!list_empty(&dev->links.defer_sync)))1216 if (WARN_ON(!list_empty(&dev->links.defer_sync)))
1144 return;1217 return;
@@ -1233,7 +1306,7 @@ static void device_link_drop_managed(struct device_link *link) · 88 unmodified lines
1233}1306}
1234 1307
1235static ssize_t waiting_for_supplier_show(struct device *dev,1308static ssize_t waiting_for_supplier_show(struct device *dev,
1236 struct device_attribute *attr,1309 const struct device_attribute *attr,
1237 char *buf)1310 char *buf)
1238{1311{
1239 bool val;1312 bool val;
@@ -1244,7 +1317,7 @@ static ssize_t waiting_for_supplier_show(struct device *dev, · 4 unmodified lines
1244 device_unlock(dev);1317 device_unlock(dev);
1245 return sysfs_emit(buf, "%u\n", val);1318 return sysfs_emit(buf, "%u\n", val);
1246}1319}
1247static DEVICE_ATTR_RO(waiting_for_supplier);1320static const DEVICE_ATTR_RO(waiting_for_supplier);
1248 1321
1249/**1322/**
1250 * device_links_force_bind - Prepares device to be force bound1323 * device_links_force_bind - Prepares device to be force bound
@@ -1312,16 +1385,8 @@ void device_links_driver_bound(struct device *dev) · 61 unmodified lines
1312 * child firmware node.1385 * child firmware node.
1313 */1386 */
1314 if (dev->fwnode && dev->fwnode->dev == dev) {1387 if (dev->fwnode && dev->fwnode->dev == dev) {
1315 struct fwnode_handle *child;
1316
1317 fwnode_links_purge_suppliers(dev->fwnode);1388 fwnode_links_purge_suppliers(dev->fwnode);
1318 1389 fw_devlink_pickup_dangling_consumers(dev);
1319 guard(mutex)(&fwnode_link_lock);
1320
1321 fwnode_for_each_available_child_node(dev->fwnode, child)
1322 __fw_devlink_pickup_dangling_consumers(child,
1323 dev->fwnode);
1324 __fw_devlink_link_to_consumers(dev);
1325 }1390 }
1326 device_remove_file(dev, &dev_attr_waiting_for_supplier);1391 device_remove_file(dev, &dev_attr_waiting_for_supplier);
1327 1392
@@ -1370,7 +1435,7 @@ void device_links_driver_bound(struct device *dev) · 42 unmodified lines
1370 } else if (dev_is_best_effort(dev) &&1435 } else if (dev_is_best_effort(dev) &&
1371 device_link_test(link, DL_FLAG_INFERRED) &&1436 device_link_test(link, DL_FLAG_INFERRED) &&
1372 link->status != DL_STATE_CONSUMER_PROBE &&1437 link->status != DL_STATE_CONSUMER_PROBE &&
1373 !link->supplier->can_match) {1438 !dev_can_match(link->supplier)) {
1374 /*1439 /*
1375 * When dev_is_best_effort() is true, we ignore device1440 * When dev_is_best_effort() is true, we ignore device
1376 * links to suppliers that don't have a driver. If the1441 * links to suppliers that don't have a driver. If the
@@ -1435,7 +1500,8 @@ static void __device_links_no_driver(struct device *dev) · 58 unmodified lines
1435 if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {1500 if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
1436 WRITE_ONCE(link->status, DL_STATE_AVAILABLE);1501 WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
1437 } else {1502 } else {
1438 WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));1503 WARN_ON(link->supplier->links.status != DL_DEV_UNBINDING &&
1504 !device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
1439 WRITE_ONCE(link->status, DL_STATE_DORMANT);1505 WRITE_ONCE(link->status, DL_STATE_DORMANT);
1440 }1506 }
1441 }1507 }
@@ -1758,7 +1824,7 @@ static int fw_devlink_no_driver(struct device *dev, void *data) · 316 unmodified lines
1758{1824{
1759 struct device_link *link = to_devlink(dev);1825 struct device_link *link = to_devlink(dev);
1760 1826
1761 if (!link->supplier->can_match)1827 if (!dev_can_match(link->supplier))
1762 fw_devlink_relax_link(link);1828 fw_devlink_relax_link(link);
1763 1829
1764 return 0;1830 return 0;
@@ -1779,7 +1845,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data) · 14 unmodified lines
1779 struct device *sup = link->supplier;1845 struct device *sup = link->supplier;
1780 1846
1781 if (!device_link_test(link, DL_FLAG_MANAGED) ||1847 if (!device_link_test(link, DL_FLAG_MANAGED) ||
1782 link->status == DL_STATE_ACTIVE || sup->state_synced ||1848 link->status == DL_STATE_ACTIVE || dev_state_synced(sup) ||
1783 !dev_has_sync_state(sup))1849 !dev_has_sync_state(sup))
1784 return 0;1850 return 0;
1785 1851
@@ -1793,7 +1859,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data) · 7 unmodified lines
1793 return 0;1859 return 0;
1794 1860
1795 dev_warn(sup, "Timed out. Forcing sync_state()\n");1861 dev_warn(sup, "Timed out. Forcing sync_state()\n");
1796 sup->state_synced = true;1862 dev_set_state_synced(sup);
1797 get_device(sup);1863 get_device(sup);
1798 list_add_tail(&sup->links.defer_sync, data);1864 list_add_tail(&sup->links.defer_sync, data);
1799 1865
@@ -2419,9 +2485,11 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, · 619 unmodified lines
2419 2485
2420 if (dev_attr->show)2486 if (dev_attr->show)
2421 ret = dev_attr->show(dev, dev_attr, buf);2487 ret = dev_attr->show(dev, dev_attr, buf);
2488 else if (dev_attr->show_const)
2489 ret = dev_attr->show_const(dev, dev_attr, buf);
2422 if (ret >= (ssize_t)PAGE_SIZE) {2490 if (ret >= (ssize_t)PAGE_SIZE) {
2423 printk("dev_attr_show: %pS returned bad count\n",2491 printk("dev_attr_show: %pS/%pS returned bad count\n",
2424 dev_attr->show);2492 dev_attr->show, dev_attr->show_const);
2425 }2493 }
2426 return ret;2494 return ret;
2427}2495}
@@ -2435,6 +2503,8 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr, · 7 unmodified lines
2435 2503
2436 if (dev_attr->store)2504 if (dev_attr->store)
2437 ret = dev_attr->store(dev, dev_attr, buf, count);2505 ret = dev_attr->store(dev, dev_attr, buf, count);
2506 else if (dev_attr->store_const)
2507 ret = dev_attr->store_const(dev, dev_attr, buf, count);
2438 return ret;2508 return ret;
2439}2509}
2440 2510
@@ -2722,7 +2792,7 @@ static const struct kset_uevent_ops device_uevent_ops = { · 281 unmodified lines
2722 .uevent = dev_uevent,2792 .uevent = dev_uevent,
2723};2793};
2724 2794
2725static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,2795static ssize_t uevent_show(struct device *dev, const struct device_attribute *attr,
2726 char *buf)2796 char *buf)
2727{2797{
2728 struct kobject *top_kobj;2798 struct kobject *top_kobj;
@@ -2765,7 +2835,7 @@ out: · 36 unmodified lines
2765 return len;2835 return len;
2766}2836}
2767 2837
2768static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,2838static ssize_t uevent_store(struct device *dev, const struct device_attribute *attr,
2769 const char *buf, size_t count)2839 const char *buf, size_t count)
2770{2840{
2771 int rc;2841 int rc;
@@ -2779,20 +2849,20 @@ static ssize_t uevent_store(struct device *dev, struct device_attribute *attr, · 7 unmodified lines
2779 2849
2780 return count;2850 return count;
2781}2851}
2782static DEVICE_ATTR_RW(uevent);2852static const DEVICE_ATTR_RW(uevent);
2783 2853
2784static ssize_t online_show(struct device *dev, struct device_attribute *attr,2854static ssize_t online_show(struct device *dev, const struct device_attribute *attr,
2785 char *buf)2855 char *buf)
2786{2856{
2787 bool val;2857 bool val;
2788 2858
2789 device_lock(dev);2859 device_lock(dev);
2790 val = !dev->offline;2860 val = !dev_offline(dev);
2791 device_unlock(dev);2861 device_unlock(dev);
2792 return sysfs_emit(buf, "%u\n", val);2862 return sysfs_emit(buf, "%u\n", val);
2793}2863}
2794 2864
2795static ssize_t online_store(struct device *dev, struct device_attribute *attr,2865static ssize_t online_store(struct device *dev, const struct device_attribute *attr,
2796 const char *buf, size_t count)2866 const char *buf, size_t count)
2797{2867{
2798 bool val;2868 bool val;
@@ -2810,9 +2880,9 @@ static ssize_t online_store(struct device *dev, struct device_attribute *attr, · 11 unmodified lines
2810 unlock_device_hotplug();2880 unlock_device_hotplug();
2811 return ret < 0 ? ret : count;2881 return ret < 0 ? ret : count;
2812}2882}
2813static DEVICE_ATTR_RW(online);2883static const DEVICE_ATTR_RW(online);
2814 2884
2815static ssize_t removable_show(struct device *dev, struct device_attribute *attr,2885static ssize_t removable_show(struct device *dev, const struct device_attribute *attr,
2816 char *buf)2886 char *buf)
2817{2887{
2818 const char *loc;2888 const char *loc;
@@ -2829,7 +2899,7 @@ static ssize_t removable_show(struct device *dev, struct device_attribute *attr, · 10 unmodified lines
2829 }2899 }
2830 return sysfs_emit(buf, "%s\n", loc);2900 return sysfs_emit(buf, "%s\n", loc);
2831}2901}
2832static DEVICE_ATTR_RO(removable);2902static const DEVICE_ATTR_RO(removable);
2833 2903
2834int device_add_groups(struct device *dev,2904int device_add_groups(struct device *dev,
2835 const struct attribute_group *const *groups)2905 const struct attribute_group *const *groups)
@@ -2913,7 +2983,7 @@ static int device_add_attrs(struct device *dev) · 77 unmodified lines
2913 if (error)2983 if (error)
2914 goto err_remove_type_groups;2984 goto err_remove_type_groups;
2915 2985
2916 if (device_supports_offline(dev) && !dev->offline_disabled) {2986 if (device_supports_offline(dev) && !dev_offline_disabled(dev)) {
2917 error = device_create_file(dev, &dev_attr_online);2987 error = device_create_file(dev, &dev_attr_online);
2918 if (error)2988 if (error)
2919 goto err_remove_dev_groups;2989 goto err_remove_dev_groups;
@@ -2980,12 +3050,12 @@ static void device_remove_attrs(struct device *dev) · 60 unmodified lines
2980 device_remove_groups(dev, class->dev_groups);3050 device_remove_groups(dev, class->dev_groups);
2981}3051}
2982 3052
2983static ssize_t dev_show(struct device *dev, struct device_attribute *attr,3053static ssize_t dev_show(struct device *dev, const struct device_attribute *attr,
2984 char *buf)3054 char *buf)
2985{3055{
2986 return print_dev_t(buf, dev->devt);3056 return print_dev_t(buf, dev->devt);
2987}3057}
2988static DEVICE_ATTR_RO(dev);3058static const DEVICE_ATTR_RO(dev);
2989 3059
2990/* /sys/devices/ */3060/* /sys/devices/ */
2991struct kset *devices_kset;3061struct kset *devices_kset;
@@ -3047,10 +3117,10 @@ int device_create_file(struct device *dev, · 55 unmodified lines
3047 int error = 0;3117 int error = 0;
3048 3118
3049 if (dev) {3119 if (dev) {
3050 WARN(((attr->attr.mode & S_IWUGO) && !attr->store),3120 WARN(((attr->attr.mode & S_IWUGO) && !(attr->store || attr->store_const)),
3051 "Attribute %s: write permission without 'store'\n",3121 "Attribute %s: write permission without 'store'\n",
3052 attr->attr.name);3122 attr->attr.name);
3053 WARN(((attr->attr.mode & S_IRUGO) && !attr->show),3123 WARN(((attr->attr.mode & S_IRUGO) && !(attr->show || attr->show_const)),
3054 "Attribute %s: read permission without 'show'\n",3124 "Attribute %s: read permission without 'show'\n",
3055 attr->attr.name);3125 attr->attr.name);
3056 error = sysfs_create_file(&dev->kobj, &attr->attr);3126 error = sysfs_create_file(&dev->kobj, &attr->attr);
@@ -3170,11 +3240,7 @@ void device_initialize(struct device *dev) · 113 unmodified lines
3170 INIT_LIST_HEAD(&dev->links.suppliers);3240 INIT_LIST_HEAD(&dev->links.suppliers);
3171 INIT_LIST_HEAD(&dev->links.defer_sync);3241 INIT_LIST_HEAD(&dev->links.defer_sync);
3172 dev->links.status = DL_DEV_NO_DRIVER;3242 dev->links.status = DL_DEV_NO_DRIVER;
3173#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \3243 dev_assign_dma_coherent(dev, dma_default_coherent);
3174 defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
3175 defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
3176 dev->dma_coherent = dma_default_coherent;
3177#endif
3178 swiotlb_dev_init(dev);3244 swiotlb_dev_init(dev);
3179}3245}
3180EXPORT_SYMBOL_GPL(device_initialize);3246EXPORT_SYMBOL_GPL(device_initialize);
@@ -3710,7 +3776,7 @@ int device_add(struct device *dev) · 529 unmodified lines
3710 * match with any driver, don't block its consumers from probing in3776 * match with any driver, don't block its consumers from probing in
3711 * case the consumer device is able to operate without this supplier.3777 * case the consumer device is able to operate without this supplier.
3712 */3778 */
3713 if (dev->fwnode && fw_devlink_drv_reg_done && !dev->can_match)3779 if (dev->fwnode && fw_devlink_drv_reg_done && !dev_can_match(dev))
3714 fw_devlink_unblock_consumers(dev);3780 fw_devlink_unblock_consumers(dev);
3715 3781
3716 if (parent)3782 if (parent)
@@ -4180,7 +4246,7 @@ static int device_check_offline(struct device *dev, void *not_used) · 463 unmodified lines
4180 if (ret)4246 if (ret)
4181 return ret;4247 return ret;
4182 4248
4183 return device_supports_offline(dev) && !dev->offline ? -EBUSY : 0;4249 return device_supports_offline(dev) && !dev_offline(dev) ? -EBUSY : 0;
4184}4250}
4185 4251
4186/**4252/**
@@ -4198,7 +4264,7 @@ int device_offline(struct device *dev) · 11 unmodified lines
4198{4264{
4199 int ret;4265 int ret;
4200 4266
4201 if (dev->offline_disabled)4267 if (dev_offline_disabled(dev))
4202 return -EPERM;4268 return -EPERM;
4203 4269
4204 ret = device_for_each_child(dev, NULL, device_check_offline);4270 ret = device_for_each_child(dev, NULL, device_check_offline);
@@ -4207,13 +4273,13 @@ int device_offline(struct device *dev) · 2 unmodified lines
4207 4273
4208 device_lock(dev);4274 device_lock(dev);
4209 if (device_supports_offline(dev)) {4275 if (device_supports_offline(dev)) {
4210 if (dev->offline) {4276 if (dev_offline(dev)) {
4211 ret = 1;4277 ret = 1;
4212 } else {4278 } else {
4213 ret = dev->bus->offline(dev);4279 ret = dev->bus->offline(dev);
4214 if (!ret) {4280 if (!ret) {
4215 kobject_uevent(&dev->kobj, KOBJ_OFFLINE);4281 kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
4216 dev->offline = true;4282 dev_set_offline(dev);
4217 }4283 }
4218 }4284 }
4219 }4285 }
@@ -4238,11 +4304,11 @@ int device_online(struct device *dev) · 18 unmodified lines
4238 4304
4239 device_lock(dev);4305 device_lock(dev);
4240 if (device_supports_offline(dev)) {4306 if (device_supports_offline(dev)) {
4241 if (dev->offline) {4307 if (dev_offline(dev)) {
4242 ret = dev->bus->online(dev);4308 ret = dev->bus->online(dev);
4243 if (!ret) {4309 if (!ret) {
4244 kobject_uevent(&dev->kobj, KOBJ_ONLINE);4310 kobject_uevent(&dev->kobj, KOBJ_ONLINE);
4245 dev->offline = false;4311 dev_clear_offline(dev);
4246 }4312 }
4247 } else {4313 } else {
4248 ret = 1;4314 ret = 1;
@@ -4716,7 +4782,7 @@ static int device_attrs_change_owner(struct device *dev, kuid_t kuid, · 467 unmodified lines
4716 if (error)4782 if (error)
4717 return error;4783 return error;
4718 4784
4719 if (device_supports_offline(dev) && !dev->offline_disabled) {4785 if (device_supports_offline(dev) && !dev_offline_disabled(dev)) {
4720 /* Change online device attributes of @dev to @kuid/@kgid. */4786 /* Change online device attributes of @dev to @kuid/@kgid. */
4721 error = sysfs_file_change_owner(kobj, dev_attr_online.attr.name,4787 error = sysfs_file_change_owner(kobj, dev_attr_online.attr.name,
4722 kuid, kgid);4788 kuid, kgid);
@@ -5283,7 +5349,7 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2) · 560 unmodified lines
5283{5349{
5284 of_node_put(dev->of_node);5350 of_node_put(dev->of_node);
5285 dev->of_node = of_node_get(dev2->of_node);5351 dev->of_node = of_node_get(dev2->of_node);
5286 dev->of_node_reused = true;5352 dev_set_of_node_reused(dev);
5287}5353}
5288EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);5354EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
5289 5355
drivers/base/cpu.c+2−2
@@ -422,8 +422,8 @@ int register_cpu(struct cpu *cpu, int num) · 421 unmodified lines
422 cpu->dev.id = num;422 cpu->dev.id = num;
423 cpu->dev.bus = &cpu_subsys;423 cpu->dev.bus = &cpu_subsys;
424 cpu->dev.release = cpu_device_release;424 cpu->dev.release = cpu_device_release;
425 cpu->dev.offline_disabled = !cpu->hotpluggable;425 dev_assign_offline_disabled(&cpu->dev, !cpu->hotpluggable);
426 cpu->dev.offline = !cpu_online(num);426 dev_assign_offline(&cpu->dev, !cpu_online(num));
427 cpu->dev.of_node = of_get_cpu_node(num, NULL);427 cpu->dev.of_node = of_get_cpu_node(num, NULL);
428 cpu->dev.groups = common_cpu_attr_groups;428 cpu->dev.groups = common_cpu_attr_groups;
429 if (cpu->hotpluggable)429 if (cpu->hotpluggable)
drivers/base/dd.c+12−15
@@ -132,7 +132,7 @@ static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func); · 131 unmodified lines
132 132
133void driver_deferred_probe_add(struct device *dev)133void driver_deferred_probe_add(struct device *dev)
134{134{
135 if (!dev->can_match)135 if (!dev_can_match(dev))
136 return;136 return;
137 137
138 mutex_lock(&deferred_probe_mutex);138 mutex_lock(&deferred_probe_mutex);
@@ -323,12 +323,11 @@ void deferred_probe_extend_timeout(void) · 184 unmodified lines
323 * If the work hasn't been queued yet or if the work expired, don't323 * If the work hasn't been queued yet or if the work expired, don't
324 * start a new one.324 * start a new one.
325 */325 */
326 if (cancel_delayed_work(&deferred_probe_timeout_work)) {326 if (delayed_work_pending(&deferred_probe_timeout_work) &&
327 schedule_delayed_work(&deferred_probe_timeout_work,327 mod_delayed_work(system_percpu_wq, &deferred_probe_timeout_work,
328 driver_deferred_probe_timeout * HZ);328 secs_to_jiffies(driver_deferred_probe_timeout)))
329 pr_debug("Extended deferred probe timeout by %d secs\n",329 pr_debug("Extended deferred probe timeout by %d secs\n",
330 driver_deferred_probe_timeout);330 driver_deferred_probe_timeout);
331 }
332}331}
333 332
334/**333/**
@@ -569,12 +568,10 @@ static ssize_t state_synced_store(struct device *dev, · 234 unmodified lines
569 return -EINVAL;568 return -EINVAL;
570 569
571 device_lock(dev);570 device_lock(dev);
572 if (!dev->state_synced) {571 if (!dev_test_and_set_state_synced(dev))
573 dev->state_synced = true;
574 dev_sync_state(dev);572 dev_sync_state(dev);
575 } else {573 else
576 ret = -EINVAL;574 ret = -EINVAL;
577 }
578 device_unlock(dev);575 device_unlock(dev);
579 576
580 return ret ? ret : count;577 return ret ? ret : count;
@@ -586,7 +583,7 @@ static ssize_t state_synced_show(struct device *dev, · 5 unmodified lines
586 bool val;583 bool val;
587 584
588 device_lock(dev);585 device_lock(dev);
589 val = dev->state_synced;586 val = dev_state_synced(dev);
590 device_unlock(dev);587 device_unlock(dev);
591 588
592 return sysfs_emit(buf, "%u\n", val);589 return sysfs_emit(buf, "%u\n", val);
@@ -595,9 +592,9 @@ static DEVICE_ATTR_RW(state_synced); · 2 unmodified lines
595 592
596static void device_unbind_cleanup(struct device *dev)593static void device_unbind_cleanup(struct device *dev)
597{594{
598 devres_release_all(dev);
599 if (dev->driver->p_cb.post_unbind_rust)595 if (dev->driver->p_cb.post_unbind_rust)
600 dev->driver->p_cb.post_unbind_rust(dev);596 dev->driver->p_cb.post_unbind_rust(dev);
597 devres_release_all(dev);
601 arch_teardown_dma_ops(dev);598 arch_teardown_dma_ops(dev);
602 kfree(dev->dma_range_map);599 kfree(dev->dma_range_map);
603 dev->dma_range_map = NULL;600 dev->dma_range_map = NULL;
@@ -849,14 +846,14 @@ static int __driver_probe_device(const struct device_driver *drv, struct device · 245 unmodified lines
849 return dev_err_probe(dev, -EPROBE_DEFER, "Device not ready to probe\n");846 return dev_err_probe(dev, -EPROBE_DEFER, "Device not ready to probe\n");
850 847
851 /*848 /*
852 * Set can_match = true after calling dev_ready_to_probe(), so849 * Call dev_set_can_match() after calling dev_ready_to_probe(), so
853 * driver_deferred_probe_add() won't actually add the device to the850 * driver_deferred_probe_add() won't actually add the device to the
854 * deferred probe list when dev_ready_to_probe() returns false.851 * deferred probe list when dev_ready_to_probe() returns false.
855 *852 *
856 * When dev_ready_to_probe() returns false, it means that device_add()853 * When dev_ready_to_probe() returns false, it means that device_add()
857 * will do another probe() attempt for us.854 * will do another probe() attempt for us.
858 */855 */
859 dev->can_match = true;856 dev_set_can_match(dev);
860 dev_dbg(dev, "bus: '%s': %s: matched device with driver %s\n",857 dev_dbg(dev, "bus: '%s': %s: matched device with driver %s\n",
861 drv->bus->name, __func__, drv->name);858 drv->bus->name, __func__, drv->name);
862 859
@@ -1002,7 +999,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data) · 139 unmodified lines
1002 return 0;999 return 0;
1003 } else if (ret == -EPROBE_DEFER) {1000 } else if (ret == -EPROBE_DEFER) {
1004 dev_dbg(dev, "Device match requests probe deferral\n");1001 dev_dbg(dev, "Device match requests probe deferral\n");
1005 dev->can_match = true;1002 dev_set_can_match(dev);
1006 driver_deferred_probe_add(dev);1003 driver_deferred_probe_add(dev);
1007 /*1004 /*
1008 * Device can't match with a driver right now, so don't attempt1005 * Device can't match with a driver right now, so don't attempt
@@ -1254,7 +1251,7 @@ static int __driver_attach(struct device *dev, void *data) · 245 unmodified lines
1254 return 0;1251 return 0;
1255 } else if (ret == -EPROBE_DEFER) {1252 } else if (ret == -EPROBE_DEFER) {
1256 dev_dbg(dev, "Device match requests probe deferral\n");1253 dev_dbg(dev, "Device match requests probe deferral\n");
1257 dev->can_match = true;1254 dev_set_can_match(dev);
1258 driver_deferred_probe_add(dev);1255 driver_deferred_probe_add(dev);
1259 /*1256 /*
1260 * Driver could not match with device, but may match with1257 * Driver could not match with device, but may match with
drivers/base/devcoredump.c+0−7
@@ -471,10 +471,3 @@ static int __init devcoredump_init(void) · 470 unmodified lines
471 return class_register(&devcd_class);471 return class_register(&devcd_class);
472}472}
473__initcall(devcoredump_init);473__initcall(devcoredump_init);
474
475static void __exit devcoredump_exit(void)
476{
477 class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
478 class_unregister(&devcd_class);
479}
480__exitcall(devcoredump_exit);
drivers/base/driver.c+2−77
@@ -30,81 +30,6 @@ static struct device *next_device(struct klist_iter *i) · 29 unmodified lines
30 return dev;30 return dev;
31}31}
32 32
33/**
34 * driver_set_override() - Helper to set or clear driver override.
35 * @dev: Device to change
36 * @override: Address of string to change (e.g. &device->driver_override);
37 * The contents will be freed and hold newly allocated override.
38 * @s: NUL-terminated string, new driver name to force a match, pass empty
39 * string to clear it ("" or "\n", where the latter is only for sysfs
40 * interface).
41 * @len: length of @s
42 *
43 * Helper to set or clear driver override in a device, intended for the cases
44 * when the driver_override field is allocated by driver/bus code.
45 *
46 * Returns: 0 on success or a negative error code on failure.
47 */
48int driver_set_override(struct device *dev, const char **override,
49 const char *s, size_t len)
50{
51 const char *new, *old;
52 char *cp;
53
54 if (!override || !s)
55 return -EINVAL;
56
57 /*
58 * The stored value will be used in sysfs show callback (sysfs_emit()),
59 * which has a length limit of PAGE_SIZE and adds a trailing newline.
60 * Thus we can store one character less to avoid truncation during sysfs
61 * show.
62 */
63 if (len >= (PAGE_SIZE - 1))
64 return -EINVAL;
65
66 /*
67 * Compute the real length of the string in case userspace sends us a
68 * bunch of \0 characters like python likes to do.
69 */
70 len = strlen(s);
71
72 if (!len) {
73 /* Empty string passed - clear override */
74 device_lock(dev);
75 old = *override;
76 *override = NULL;
77 device_unlock(dev);
78 kfree(old);
79
80 return 0;
81 }
82
83 cp = strnchr(s, len, '\n');
84 if (cp)
85 len = cp - s;
86
87 new = kstrndup(s, len, GFP_KERNEL);
88 if (!new)
89 return -ENOMEM;
90
91 device_lock(dev);
92 old = *override;
93 if (cp != s) {
94 *override = new;
95 } else {
96 /* "\n" passed - clear override */
97 kfree(new);
98 *override = NULL;
99 }
100 device_unlock(dev);
101
102 kfree(old);
103
104 return 0;
105}
106EXPORT_SYMBOL_GPL(driver_set_override);
107
108/**33/**
109 * driver_for_each_device - Iterator for devices bound to a driver.34 * driver_for_each_device - Iterator for devices bound to a driver.
110 * @drv: Driver we're iterating.35 * @drv: Driver we're iterating.
@@ -203,13 +128,13 @@ void driver_remove_file(const struct device_driver *drv, · 92 unmodified lines
203EXPORT_SYMBOL_GPL(driver_remove_file);128EXPORT_SYMBOL_GPL(driver_remove_file);
204 129
205int driver_add_groups(const struct device_driver *drv,130int driver_add_groups(const struct device_driver *drv,
206 const struct attribute_group **groups)131 const struct attribute_group *const *groups)
207{132{
208 return sysfs_create_groups(&drv->p->kobj, groups);133 return sysfs_create_groups(&drv->p->kobj, groups);
209}134}
210 135
211void driver_remove_groups(const struct device_driver *drv,136void driver_remove_groups(const struct device_driver *drv,
212 const struct attribute_group **groups)137 const struct attribute_group *const *groups)
213{138{
214 sysfs_remove_groups(&drv->p->kobj, groups);139 sysfs_remove_groups(&drv->p->kobj, groups);
215}140}
drivers/base/faux.c+15−17
@@ -133,6 +133,9 @@ struct faux_device *faux_device_create_with_groups(const char *name, · 132 unmodified lines
133 struct device *dev;133 struct device *dev;
134 int ret;134 int ret;
135 135
136 if (!faux_bus_root)
137 return NULL;
138
136 faux_obj = kzalloc_obj(*faux_obj);139 faux_obj = kzalloc_obj(*faux_obj);
137 if (!faux_obj)140 if (!faux_obj)
138 return NULL;141 return NULL;
@@ -232,34 +235,29 @@ EXPORT_SYMBOL_GPL(faux_device_destroy); · 93 unmodified lines
232 235
233int __init faux_bus_init(void)236int __init faux_bus_init(void)
234{237{
238 struct device *root;
235 int ret;239 int ret;
236 240
237 faux_bus_root = kzalloc_obj(*faux_bus_root);241 root = root_device_register("faux");
238 if (!faux_bus_root)242 if (IS_ERR(root))
239 return -ENOMEM;243 return PTR_ERR(root);
240
241 dev_set_name(faux_bus_root, "faux");
242
243 ret = device_register(faux_bus_root);
244 if (ret) {
245 put_device(faux_bus_root);
246 return ret;
247 }
248 244
249 ret = bus_register(&faux_bus_type);245 ret = bus_register(&faux_bus_type);
250 if (ret)246 if (ret)
251 goto error_bus;247 goto err_deregister_root;
252 248
253 ret = driver_register(&faux_driver);249 ret = driver_register(&faux_driver);
254 if (ret)250 if (ret)
255 goto error_driver;251 goto err_deregister_bus;
256 252
257 return ret;253 faux_bus_root = root;
254
255 return 0;
258 256
259error_driver:257err_deregister_bus:
260 bus_unregister(&faux_bus_type);258 bus_unregister(&faux_bus_type);
259err_deregister_root:
260 root_device_unregister(root);
261 261
262error_bus:
263 device_unregister(faux_bus_root);
264 return ret;262 return ret;
265}263}
drivers/base/firmware_loader/main.c+2−1
@@ -1503,9 +1503,10 @@ static void device_cache_fw_images(void) · 1502 unmodified lines
1503 1503
1504 mutex_lock(&fw_lock);1504 mutex_lock(&fw_lock);
1505 fwc->state = FW_LOADER_START_CACHE;1505 fwc->state = FW_LOADER_START_CACHE;
1506 dpm_for_each_dev(NULL, dev_cache_fw_image);
1507 mutex_unlock(&fw_lock);1506 mutex_unlock(&fw_lock);
1508 1507
1508 dpm_for_each_dev(NULL, dev_cache_fw_image);
1509
1509 /* wait for completion of caching firmware for all devices */1510 /* wait for completion of caching firmware for all devices */
1510 async_synchronize_full_domain(&fw_cache_domain);1511 async_synchronize_full_domain(&fw_cache_domain);
1511 1512
drivers/base/firmware_loader/sysfs_upload.c+3−5
@@ -343,7 +343,6 @@ firmware_upload_register(struct module *module, struct device *parent, · 342 unmodified lines
343 goto free_fw_upload_priv;343 goto free_fw_upload_priv;
344 }344 }
345 fw_upload->priv = fw_sysfs;345 fw_upload->priv = fw_sysfs;
346 fw_sysfs->fw_upload_priv = fw_upload_priv;
347 fw_dev = &fw_sysfs->dev;346 fw_dev = &fw_sysfs->dev;
348 347
349 ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv, NULL, 0, 0,348 ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv, NULL, 0, 0,
@@ -351,10 +350,12 @@ firmware_upload_register(struct module *module, struct device *parent, · 1 unmodified line
351 if (ret != 0) {350 if (ret != 0) {
352 if (ret > 0)351 if (ret > 0)
353 ret = -EINVAL;352 ret = -EINVAL;
354 goto free_fw_sysfs;353 put_device(fw_dev);
354 goto free_fw_upload_priv;
355 }355 }
356 fw_priv->is_paged_buf = true;356 fw_priv->is_paged_buf = true;
357 fw_sysfs->fw_priv = fw_priv;357 fw_sysfs->fw_priv = fw_priv;
358 fw_sysfs->fw_upload_priv = fw_upload_priv;
358 359
359 ret = device_add(fw_dev);360 ret = device_add(fw_dev);
360 if (ret) {361 if (ret) {
@@ -365,9 +366,6 @@ firmware_upload_register(struct module *module, struct device *parent, · 4 unmodified lines
365 366
366 return fw_upload;367 return fw_upload;
367 368
368free_fw_sysfs:
369 kfree(fw_sysfs);
370
371free_fw_upload_priv:369free_fw_upload_priv:
372 kfree(fw_upload_priv);370 kfree(fw_upload_priv);
373 371
drivers/base/isa.c+6−6
@@ -11,9 +11,7 @@ · 10 unmodified lines
11#include <linux/dma-mapping.h>11#include <linux/dma-mapping.h>
12#include <linux/isa.h>12#include <linux/isa.h>
13 13
14static struct device isa_bus = {14static struct device *isa_bus;
15 .init_name = "isa"
16};
17 15
18struct isa_dev {16struct isa_dev {
19 struct device dev;17 struct device dev;
@@ -131,7 +129,7 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) · 111 unmodified lines
131 break;129 break;
132 }130 }
133 131
134 isa_dev->dev.parent = &isa_bus;132 isa_dev->dev.parent = isa_bus;
135 isa_dev->dev.bus = &isa_bus_type;133 isa_dev->dev.bus = &isa_bus_type;
136 134
137 dev_set_name(&isa_dev->dev, "%s.%u",135 dev_set_name(&isa_dev->dev, "%s.%u",
@@ -169,9 +167,11 @@ static int __init isa_bus_init(void) · 31 unmodified lines
169 167
170 error = bus_register(&isa_bus_type);168 error = bus_register(&isa_bus_type);
171 if (!error) {169 if (!error) {
172 error = device_register(&isa_bus);170 isa_bus = root_device_register("isa");
173 if (error)171 if (IS_ERR(isa_bus)) {
172 error = PTR_ERR(isa_bus);
174 bus_unregister(&isa_bus_type);173 bus_unregister(&isa_bus_type);
174 }
175 }175 }
176 return error;176 return error;
177}177}
drivers/base/memory.c+1−1
@@ -697,7 +697,7 @@ static int __add_memory_block(struct memory_block *memory) · 696 unmodified lines
697 memory->dev.id = memory->start_section_nr / sections_per_block;697 memory->dev.id = memory->start_section_nr / sections_per_block;
698 memory->dev.release = memory_block_release;698 memory->dev.release = memory_block_release;
699 memory->dev.groups = memory_memblk_attr_groups;699 memory->dev.groups = memory_memblk_attr_groups;
700 memory->dev.offline = memory->state == MEM_OFFLINE;700 dev_assign_offline(&memory->dev, memory->state == MEM_OFFLINE);
701 701
702 ret = device_register(&memory->dev);702 ret = device_register(&memory->dev);
703 if (ret) {703 if (ret) {
drivers/base/pinctrl.c+1−1
@@ -24,7 +24,7 @@ int pinctrl_bind_pins(struct device *dev) · 23 unmodified lines
24{24{
25 int ret;25 int ret;
26 26
27 if (dev->of_node_reused)27 if (dev_of_node_reused(dev))
28 return 0;28 return 0;
29 29
30 dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);30 dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);
drivers/base/platform.c+15−8
@@ -870,7 +870,7 @@ struct platform_device *platform_device_register_full(const struct platform_devi · 869 unmodified lines
870 pdev->dev.parent = pdevinfo->parent;870 pdev->dev.parent = pdevinfo->parent;
871 pdev->dev.fwnode = pdevinfo->fwnode;871 pdev->dev.fwnode = pdevinfo->fwnode;
872 pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode));872 pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode));
873 pdev->dev.of_node_reused = pdevinfo->of_node_reused;873 dev_assign_of_node_reused(&pdev->dev, pdevinfo->of_node_reused);
874 874
875 if (pdevinfo->dma_mask) {875 if (pdevinfo->dma_mask) {
876 pdev->platform_dma_mask = pdevinfo->dma_mask;876 pdev->platform_dma_mask = pdevinfo->dma_mask;
@@ -915,11 +915,14 @@ EXPORT_SYMBOL_GPL(platform_device_register_full); · 38 unmodified lines
915 * __platform_driver_register - register a driver for platform-level devices915 * __platform_driver_register - register a driver for platform-level devices
916 * @drv: platform driver structure916 * @drv: platform driver structure
917 * @owner: owning module/driver917 * @owner: owning module/driver
918 * @mod_name: module name string
918 */919 */
919int __platform_driver_register(struct platform_driver *drv, struct module *owner)920int __platform_driver_register(struct platform_driver *drv, struct module *owner,
921 const char *mod_name)
920{922{
921 drv->driver.owner = owner;923 drv->driver.owner = owner;
922 drv->driver.bus = &platform_bus_type;924 drv->driver.bus = &platform_bus_type;
925 drv->driver.mod_name = mod_name;
923 926
924 return driver_register(&drv->driver);927 return driver_register(&drv->driver);
925}928}
@@ -952,6 +955,7 @@ static int is_bound_to_driver(struct device *dev, void *driver) · 26 unmodified lines
952 * @drv: platform driver structure955 * @drv: platform driver structure
953 * @probe: the driver probe routine, probably from an __init section956 * @probe: the driver probe routine, probably from an __init section
954 * @module: module which will be the owner of the driver957 * @module: module which will be the owner of the driver
958 * @mod_name: module name string
955 *959 *
956 * Use this instead of platform_driver_register() when you know the device960 * Use this instead of platform_driver_register() when you know the device
957 * is not hotpluggable and has already been registered, and you want to961 * is not hotpluggable and has already been registered, and you want to
@@ -969,7 +973,8 @@ static int is_bound_to_driver(struct device *dev, void *driver) · 11 unmodified lines
969 */973 */
970int __init_or_module __platform_driver_probe(struct platform_driver *drv,974int __init_or_module __platform_driver_probe(struct platform_driver *drv,
971 int (*probe)(struct platform_device *),975 int (*probe)(struct platform_device *),
972 struct module *module)976 struct module *module,
977 const char *mod_name)
973{978{
974 int retval;979 int retval;
975 980
@@ -997,7 +1002,7 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv, · 21 unmodified lines
997 1002
998 /* temporary section violation during probe() */1003 /* temporary section violation during probe() */
999 drv->probe = probe;1004 drv->probe = probe;
1000 retval = __platform_driver_register(drv, module);1005 retval = __platform_driver_register(drv, module, mod_name);
1001 if (retval)1006 if (retval)
1002 return retval;1007 return retval;
1003 1008
@@ -1025,6 +1030,7 @@ EXPORT_SYMBOL_GPL(__platform_driver_probe); · 21 unmodified lines
1025 * @data: platform specific data for this platform device1030 * @data: platform specific data for this platform device
1026 * @size: size of platform specific data1031 * @size: size of platform specific data
1027 * @module: module which will be the owner of the driver1032 * @module: module which will be the owner of the driver
1033 * @mod_name: module name string
1028 *1034 *
1029 * Use this in legacy-style modules that probe hardware directly and1035 * Use this in legacy-style modules that probe hardware directly and
1030 * register a single platform device and corresponding platform driver.1036 * register a single platform device and corresponding platform driver.
@@ -1035,7 +1041,7 @@ struct platform_device * __init_or_module · 4 unmodified lines
1035__platform_create_bundle(struct platform_driver *driver,1041__platform_create_bundle(struct platform_driver *driver,
1036 int (*probe)(struct platform_device *),1042 int (*probe)(struct platform_device *),
1037 struct resource *res, unsigned int n_res,1043 struct resource *res, unsigned int n_res,
1038 const void *data, size_t size, struct module *module)1044 const void *data, size_t size, struct module *module, const char *mod_name)
1039{1045{
1040 struct platform_device *pdev;1046 struct platform_device *pdev;
1041 int error;1047 int error;
@@ -1058,7 +1064,7 @@ __platform_create_bundle(struct platform_driver *driver, · 16 unmodified lines
1058 if (error)1064 if (error)
1059 goto err_pdev_put;1065 goto err_pdev_put;
1060 1066
1061 error = __platform_driver_probe(driver, probe, module);1067 error = __platform_driver_probe(driver, probe, module, mod_name);
1062 if (error)1068 if (error)
1063 goto err_pdev_del;1069 goto err_pdev_del;
1064 1070
@@ -1078,6 +1084,7 @@ EXPORT_SYMBOL_GPL(__platform_create_bundle); · 13 unmodified lines
1078 * @drivers: an array of drivers to register1084 * @drivers: an array of drivers to register
1079 * @count: the number of drivers to register1085 * @count: the number of drivers to register
1080 * @owner: module owning the drivers1086 * @owner: module owning the drivers
1087 * @mod_name: module name string
1081 *1088 *
1082 * Registers platform drivers specified by an array. On failure to register a1089 * Registers platform drivers specified by an array. On failure to register a
1083 * driver, all previously registered drivers will be unregistered. Callers of1090 * driver, all previously registered drivers will be unregistered. Callers of
@@ -1087,7 +1094,7 @@ EXPORT_SYMBOL_GPL(__platform_create_bundle); · 3 unmodified lines
1087 * Returns: 0 on success or a negative error code on failure.1094 * Returns: 0 on success or a negative error code on failure.
1088 */1095 */
1089int __platform_register_drivers(struct platform_driver * const *drivers,1096int __platform_register_drivers(struct platform_driver * const *drivers,
1090 unsigned int count, struct module *owner)1097 unsigned int count, struct module *owner, const char *mod_name)
1091{1098{
1092 unsigned int i;1099 unsigned int i;
1093 int err;1100 int err;
@@ -1095,7 +1102,7 @@ int __platform_register_drivers(struct platform_driver * const *drivers, · 1 unmodified line
1095 for (i = 0; i < count; i++) {1102 for (i = 0; i < count; i++) {
1096 pr_debug("registering platform driver %ps\n", drivers[i]);1103 pr_debug("registering platform driver %ps\n", drivers[i]);
1097 1104
1098 err = __platform_driver_register(drivers[i], owner);1105 err = __platform_driver_register(drivers[i], owner, mod_name);
1099 if (err < 0) {1106 if (err < 0) {
1100 pr_err("failed to register platform driver %ps: %d\n",1107 pr_err("failed to register platform driver %ps: %d\n",
1101 drivers[i], err);1108 drivers[i], err);
drivers/base/property.c+3−1
@@ -1277,8 +1277,10 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode, · 1276 unmodified lines
1277 if (fwnode_ep.port != port)1277 if (fwnode_ep.port != port)
1278 continue;1278 continue;
1279 1279
1280 if (fwnode_ep.id == endpoint)1280 if (fwnode_ep.id == endpoint) {
1281 fwnode_handle_put(best_ep);
1281 return ep;1282 return ep;
1283 }
1282 1284
1283 if (!endpoint_next)1285 if (!endpoint_next)
1284 continue;1286 continue;
drivers/base/swnode.c+24−16
@@ -374,20 +374,28 @@ EXPORT_SYMBOL_GPL(property_entries_free); · 373 unmodified lines
374/* -------------------------------------------------------------------------- */374/* -------------------------------------------------------------------------- */
375/* fwnode operations */375/* fwnode operations */
376 376
377static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode)377static struct swnode *swnode_get(struct swnode *swnode)
378{378{
379 struct swnode *swnode = to_swnode(fwnode);
380
381 kobject_get(&swnode->kobj);379 kobject_get(&swnode->kobj);
382 380
381 return swnode;
382}
383
384static void swnode_put(struct swnode *swnode)
385{
386 kobject_put(&swnode->kobj);
387}
388
389static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode)
390{
391 struct swnode *swnode = swnode_get(to_swnode(fwnode));
392
383 return &swnode->fwnode;393 return &swnode->fwnode;
384}394}
385 395
386static void software_node_put(struct fwnode_handle *fwnode)396static void software_node_put(struct fwnode_handle *fwnode)
387{397{
388 struct swnode *swnode = to_swnode(fwnode);398 swnode_put(to_swnode(fwnode));
389
390 kobject_put(&swnode->kobj);
391}399}
392 400
393static bool software_node_property_present(const struct fwnode_handle *fwnode,401static bool software_node_property_present(const struct fwnode_handle *fwnode,
@@ -493,7 +501,7 @@ software_node_get_named_child_node(const struct fwnode_handle *fwnode, · 99 unmodified lines
493 501
494 list_for_each_entry(child, &swnode->children, entry) {502 list_for_each_entry(child, &swnode->children, entry) {
495 if (!strcmp(childname, kobject_name(&child->kobj))) {503 if (!strcmp(childname, kobject_name(&child->kobj))) {
496 kobject_get(&child->kobj);504 swnode_get(child);
497 return &child->fwnode;505 return &child->fwnode;
498 }506 }
499 }507 }
@@ -737,7 +745,7 @@ software_node_find_by_name(const struct software_node *parent, const char *name) · 237 unmodified lines
737 swnode = kobj_to_swnode(k);745 swnode = kobj_to_swnode(k);
738 if (parent == swnode->node->parent && swnode->node->name &&746 if (parent == swnode->node->parent && swnode->node->name &&
739 !strcmp(name, swnode->node->name)) {747 !strcmp(name, swnode->node->name)) {
740 kobject_get(&swnode->kobj);748 swnode_get(swnode);
741 break;749 break;
742 }750 }
743 swnode = NULL;751 swnode = NULL;
@@ -835,13 +843,13 @@ swnode_register(const struct software_node *node, struct swnode *parent, · 91 unmodified lines
835 parent ? &parent->kobj : NULL,843 parent ? &parent->kobj : NULL,
836 "node%d", swnode->id);844 "node%d", swnode->id);
837 if (ret) {845 if (ret) {
838 kobject_put(&swnode->kobj);846 swnode_put(swnode);
839 return ERR_PTR(ret);847 return ERR_PTR(ret);
840 }848 }
841 849
842 /*850 /*
843 * Assign the flag only in the successful case, so851 * Assign the flag only in the successful case, so
844 * the above kobject_put() won't mess up with properties.852 * the above swnode_put() won't mess up with properties.
845 */853 */
846 swnode->allocated = allocated;854 swnode->allocated = allocated;
847 855
@@ -978,7 +986,7 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode) · 130 unmodified lines
978 if (!swnode)986 if (!swnode)
979 return;987 return;
980 988
981 kobject_put(&swnode->kobj);989 swnode_put(swnode);
982}990}
983EXPORT_SYMBOL_GPL(fwnode_remove_software_node);991EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
984 992
@@ -1002,7 +1010,7 @@ int device_add_software_node(struct device *dev, const struct software_node *nod · 17 unmodified lines
1002 1010
1003 swnode = software_node_to_swnode(node);1011 swnode = software_node_to_swnode(node);
1004 if (swnode) {1012 if (swnode) {
1005 kobject_get(&swnode->kobj);1013 swnode_get(swnode);
1006 } else {1014 } else {
1007 ret = software_node_register(node);1015 ret = software_node_register(node);
1008 if (ret)1016 if (ret)
@@ -1044,7 +1052,7 @@ void device_remove_software_node(struct device *dev) · 35 unmodified lines
1044 software_node_notify_remove(dev);1052 software_node_notify_remove(dev);
1045 1053
1046 set_secondary_fwnode(dev, NULL);1054 set_secondary_fwnode(dev, NULL);
1047 kobject_put(&swnode->kobj);1055 swnode_put(swnode);
1048}1056}
1049EXPORT_SYMBOL_GPL(device_remove_software_node);1057EXPORT_SYMBOL_GPL(device_remove_software_node);
1050 1058
@@ -1097,7 +1105,7 @@ void software_node_notify(struct device *dev) · 46 unmodified lines
1097 if (!swnode)1105 if (!swnode)
1098 return;1106 return;
1099 1107
1100 kobject_get(&swnode->kobj);1108 swnode_get(swnode);
1101 ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node");1109 ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node");
1102 if (ret)1110 if (ret)
1103 return;1111 return;
@@ -1119,11 +1127,11 @@ void software_node_notify_remove(struct device *dev) · 15 unmodified lines
1119 1127
1120 sysfs_remove_link(&swnode->kobj, dev_name(dev));1128 sysfs_remove_link(&swnode->kobj, dev_name(dev));
1121 sysfs_remove_link(&dev->kobj, "software_node");1129 sysfs_remove_link(&dev->kobj, "software_node");
1122 kobject_put(&swnode->kobj);1130 swnode_put(swnode);
1123 1131
1124 if (swnode->managed) {1132 if (swnode->managed) {
1125 set_secondary_fwnode(dev, NULL);1133 set_secondary_fwnode(dev, NULL);
1126 kobject_put(&swnode->kobj);1134 swnode_put(swnode);
1127 }1135 }
1128}1136}
1129 1137
drivers/bus/imx-weim.c+0−6
@@ -327,12 +327,6 @@ static int of_weim_notify(struct notifier_block *nb, unsigned long action, · 326 unmodified lines
327 "Failed to setup timing for '%pOF'\n", rd->dn);327 "Failed to setup timing for '%pOF'\n", rd->dn);
328 328
329 if (!of_node_check_flag(rd->dn, OF_POPULATED)) {329 if (!of_node_check_flag(rd->dn, OF_POPULATED)) {
330 /*
331 * Clear the flag before adding the device so that
332 * fw_devlink doesn't skip adding consumers to this
333 * device.
334 */
335 fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
336 if (!of_platform_device_create(rd->dn, NULL, &pdev->dev)) {330 if (!of_platform_device_create(rd->dn, NULL, &pdev->dev)) {
337 dev_err(&pdev->dev,331 dev_err(&pdev->dev,
338 "Failed to create child device '%pOF'\n",332 "Failed to create child device '%pOF'\n",
drivers/cdx/cdx.c+5−35
@@ -156,8 +156,6 @@ static int cdx_unregister_device(struct device *dev, · 155 unmodified lines
156 } else {156 } else {
157 cdx_destroy_res_attr(cdx_dev, MAX_CDX_DEV_RESOURCES);157 cdx_destroy_res_attr(cdx_dev, MAX_CDX_DEV_RESOURCES);
158 debugfs_remove_recursive(cdx_dev->debugfs_dir);158 debugfs_remove_recursive(cdx_dev->debugfs_dir);
159 kfree(cdx_dev->driver_override);
160 cdx_dev->driver_override = NULL;
161 }159 }
162 160
163 /*161 /*
@@ -268,6 +266,7 @@ static int cdx_bus_match(struct device *dev, const struct device_driver *drv) · 104 unmodified lines
268 const struct cdx_driver *cdx_drv = to_cdx_driver(drv);266 const struct cdx_driver *cdx_drv = to_cdx_driver(drv);
269 const struct cdx_device_id *found_id = NULL;267 const struct cdx_device_id *found_id = NULL;
270 const struct cdx_device_id *ids;268 const struct cdx_device_id *ids;
269 int ret;
271 270
272 if (cdx_dev->is_bus)271 if (cdx_dev->is_bus)
273 return false;272 return false;
@@ -275,7 +274,8 @@ static int cdx_bus_match(struct device *dev, const struct device_driver *drv) · 1 unmodified line
275 ids = cdx_drv->match_id_table;274 ids = cdx_drv->match_id_table;
276 275
277 /* When driver_override is set, only bind to the matching driver */276 /* When driver_override is set, only bind to the matching driver */
278 if (cdx_dev->driver_override && strcmp(cdx_dev->driver_override, drv->name))277 ret = device_match_driver_override(dev, drv);
278 if (ret == 0)
279 return false;279 return false;
280 280
281 found_id = cdx_match_id(ids, cdx_dev);281 found_id = cdx_match_id(ids, cdx_dev);
@@ -289,7 +289,7 @@ static int cdx_bus_match(struct device *dev, const struct device_driver *drv) · 7 unmodified lines
289 */289 */
290 if (!found_id->override_only)290 if (!found_id->override_only)
291 return true;291 return true;
292 if (cdx_dev->driver_override)292 if (ret > 0)
293 return true;293 return true;
294 294
295 ids = found_id + 1;295 ids = found_id + 1;
@@ -453,36 +453,6 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, · 157 unmodified lines
453}453}
454static DEVICE_ATTR_RO(modalias);454static DEVICE_ATTR_RO(modalias);
455 455
456static ssize_t driver_override_store(struct device *dev,
457 struct device_attribute *attr,
458 const char *buf, size_t count)
459{
460 struct cdx_device *cdx_dev = to_cdx_device(dev);
461 int ret;
462
463 if (WARN_ON(dev->bus != &cdx_bus_type))
464 return -EINVAL;
465
466 ret = driver_set_override(dev, &cdx_dev->driver_override, buf, count);
467 if (ret)
468 return ret;
469
470 return count;
471}
472
473static ssize_t driver_override_show(struct device *dev,
474 struct device_attribute *attr, char *buf)
475{
476 struct cdx_device *cdx_dev = to_cdx_device(dev);
477 ssize_t len;
478
479 device_lock(dev);
480 len = sysfs_emit(buf, "%s\n", cdx_dev->driver_override);
481 device_unlock(dev);
482 return len;
483}
484static DEVICE_ATTR_RW(driver_override);
485
486static ssize_t enable_store(struct device *dev, struct device_attribute *attr,456static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
487 const char *buf, size_t count)457 const char *buf, size_t count)
488{458{
@@ -552,7 +522,6 @@ static struct attribute *cdx_dev_attrs[] = { · 63 unmodified lines
552 &dev_attr_class.attr,522 &dev_attr_class.attr,
553 &dev_attr_revision.attr,523 &dev_attr_revision.attr,
554 &dev_attr_modalias.attr,524 &dev_attr_modalias.attr,
555 &dev_attr_driver_override.attr,
556 NULL,525 NULL,
557};526};
558 527
@@ -646,6 +615,7 @@ ATTRIBUTE_GROUPS(cdx_bus); · 87 unmodified lines
646 615
647const struct bus_type cdx_bus_type = {616const struct bus_type cdx_bus_type = {
648 .name = "cdx",617 .name = "cdx",
618 .driver_override = true,
649 .match = cdx_bus_match,619 .match = cdx_bus_match,
650 .probe = cdx_probe,620 .probe = cdx_probe,
651 .remove = cdx_remove,621 .remove = cdx_remove,
drivers/cpufreq/rcpufreq_dt.rs+5−4
@@ -201,12 +201,13 @@ kernel::of_device_table!( · 200 unmodified lines
201 201
202impl platform::Driver for CPUFreqDTDriver {202impl platform::Driver for CPUFreqDTDriver {
203 type IdInfo = ();203 type IdInfo = ();
204 type Data<'bound> = Self;
204 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);205 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
205 206
206 fn probe(207 fn probe<'bound>(
207 pdev: &platform::Device<Core>,208 pdev: &'bound platform::Device<Core<'_>>,
208 _id_info: Option<&Self::IdInfo>,209 _id_info: Option<&'bound Self::IdInfo>,
209 ) -> impl PinInit<Self, Error> {210 ) -> impl PinInit<Self, Error> + 'bound {
210 cpufreq::Registration::<CPUFreqDTDriver>::new_foreign_owned(pdev.as_ref())?;211 cpufreq::Registration::<CPUFreqDTDriver>::new_foreign_owned(pdev.as_ref())?;
211 Ok(Self {})212 Ok(Self {})
212 }213 }
drivers/devfreq/devfreq-event.c+13−10
@@ -17,7 +17,13 @@ · 16 unmodified lines
17#include <linux/list.h>17#include <linux/list.h>
18#include <linux/of.h>18#include <linux/of.h>
19 19
20static struct class *devfreq_event_class;20static struct attribute *devfreq_event_attrs[];
21ATTRIBUTE_GROUPS(devfreq_event);
22
23static const struct class devfreq_event_class = {
24 .name = "devfreq-event",
25 .dev_groups = devfreq_event_groups
26};
21 27
22/* The list of all devfreq event list */28/* The list of all devfreq event list */
23static LIST_HEAD(devfreq_event_list);29static LIST_HEAD(devfreq_event_list);
@@ -321,7 +327,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, · 297 unmodified lines
321 edev->desc = desc;327 edev->desc = desc;
322 edev->enable_count = 0;328 edev->enable_count = 0;
323 edev->dev.parent = dev;329 edev->dev.parent = dev;
324 edev->dev.class = devfreq_event_class;330 edev->dev.class = &devfreq_event_class;
325 edev->dev.release = devfreq_event_release_edev;331 edev->dev.release = devfreq_event_release_edev;
326 332
327 dev_set_name(&edev->dev, "event%d", atomic_inc_return(&event_no));333 dev_set_name(&edev->dev, "event%d", atomic_inc_return(&event_no));
@@ -461,18 +467,15 @@ static struct attribute *devfreq_event_attrs[] = { · 133 unmodified lines
461 &dev_attr_enable_count.attr,467 &dev_attr_enable_count.attr,
462 NULL,468 NULL,
463};469};
464ATTRIBUTE_GROUPS(devfreq_event);
465 470
466static int __init devfreq_event_init(void)471static int __init devfreq_event_init(void)
467{472{
468 devfreq_event_class = class_create("devfreq-event");473 int err;
469 if (IS_ERR(devfreq_event_class)) {
470 pr_err("%s: couldn't create class\n", __FILE__);
471 return PTR_ERR(devfreq_event_class);
472 }
473 474
474 devfreq_event_class->dev_groups = devfreq_event_groups;475 err = class_register(&devfreq_event_class);
476 if (err)
477 pr_err("%s: couldn't create class\n", __FILE__);
475 478
476 return 0;479 return err;
477}480}
478subsys_initcall(devfreq_event_init);481subsys_initcall(devfreq_event_init);
drivers/dma/ti/k3-udma-glue.c+3−3
@@ -312,7 +312,7 @@ k3_udma_glue_request_tx_chn_common(struct device *dev, · 311 unmodified lines
312 312
313 if (xudma_is_pktdma(tx_chn->common.udmax)) {313 if (xudma_is_pktdma(tx_chn->common.udmax)) {
314 /* prepare the channel device as coherent */314 /* prepare the channel device as coherent */
315 tx_chn->common.chan_dev.dma_coherent = true;315 dev_set_dma_coherent(&tx_chn->common.chan_dev);
316 dma_coerce_mask_and_coherent(&tx_chn->common.chan_dev,316 dma_coerce_mask_and_coherent(&tx_chn->common.chan_dev,
317 DMA_BIT_MASK(48));317 DMA_BIT_MASK(48));
318 }318 }
@@ -1003,7 +1003,7 @@ k3_udma_glue_request_rx_chn_priv(struct device *dev, const char *name, · 684 unmodified lines
1003 1003
1004 if (xudma_is_pktdma(rx_chn->common.udmax)) {1004 if (xudma_is_pktdma(rx_chn->common.udmax)) {
1005 /* prepare the channel device as coherent */1005 /* prepare the channel device as coherent */
1006 rx_chn->common.chan_dev.dma_coherent = true;1006 dev_set_dma_coherent(&rx_chn->common.chan_dev);
1007 dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,1007 dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
1008 DMA_BIT_MASK(48));1008 DMA_BIT_MASK(48));
1009 }1009 }
@@ -1104,7 +1104,7 @@ k3_udma_glue_request_remote_rx_chn_common(struct k3_udma_glue_rx_channel *rx_chn · 94 unmodified lines
1104 1104
1105 if (xudma_is_pktdma(rx_chn->common.udmax)) {1105 if (xudma_is_pktdma(rx_chn->common.udmax)) {
1106 /* prepare the channel device as coherent */1106 /* prepare the channel device as coherent */
1107 rx_chn->common.chan_dev.dma_coherent = true;1107 dev_set_dma_coherent(&rx_chn->common.chan_dev);
1108 dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,1108 dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
1109 DMA_BIT_MASK(48));1109 DMA_BIT_MASK(48));
1110 rx_chn->single_fdq = false;1110 rx_chn->single_fdq = false;
drivers/dma/ti/k3-udma.c+3−3
@@ -428,18 +428,18 @@ static void k3_configure_chan_coherency(struct dma_chan *chan, u32 asel) · 427 unmodified lines
428 /* No special handling for the channel */428 /* No special handling for the channel */
429 chan->dev->chan_dma_dev = false;429 chan->dev->chan_dma_dev = false;
430 430
431 chan_dev->dma_coherent = false;431 dev_clear_dma_coherent(chan_dev);
432 chan_dev->dma_parms = NULL;432 chan_dev->dma_parms = NULL;
433 } else if (asel == 14 || asel == 15) {433 } else if (asel == 14 || asel == 15) {
434 chan->dev->chan_dma_dev = true;434 chan->dev->chan_dma_dev = true;
435 435
436 chan_dev->dma_coherent = true;436 dev_set_dma_coherent(chan_dev);
437 dma_coerce_mask_and_coherent(chan_dev, DMA_BIT_MASK(48));437 dma_coerce_mask_and_coherent(chan_dev, DMA_BIT_MASK(48));
438 chan_dev->dma_parms = chan_dev->parent->dma_parms;438 chan_dev->dma_parms = chan_dev->parent->dma_parms;
439 } else {439 } else {
440 dev_warn(chan->device->dev, "Invalid ASEL value: %u\n", asel);440 dev_warn(chan->device->dev, "Invalid ASEL value: %u\n", asel);
441 441
442 chan_dev->dma_coherent = false;442 dev_clear_dma_coherent(chan_dev);
443 chan_dev->dma_parms = NULL;443 chan_dev->dma_parms = NULL;
444 }444 }
445}445}
drivers/gpu/drm/nova/driver.rs+5−1
@@ -51,9 +51,13 @@ kernel::auxiliary_device_table!( · 50 unmodified lines
51 51
52impl auxiliary::Driver for NovaDriver {52impl auxiliary::Driver for NovaDriver {
53 type IdInfo = ();53 type IdInfo = ();
54 type Data<'bound> = Self;
54 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;55 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
55 56
56 fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {57 fn probe<'bound>(
58 adev: &'bound auxiliary::Device<Core<'_>>,
59 _info: &'bound Self::IdInfo,
60 ) -> impl PinInit<Self, Error> + 'bound {
57 let data = try_pin_init!(NovaData { adev: adev.into() });61 let data = try_pin_init!(NovaData { adev: adev.into() });
58 62
59 let drm = drm::Device::<Self>::new(adev.as_ref(), data)?;63 let drm = drm::Device::<Self>::new(adev.as_ref(), data)?;
drivers/gpu/drm/tyr/driver.rs+7−6
@@ -37,7 +37,7 @@ use crate::{ · 36 unmodified lines
37 regs, //37 regs, //
38};38};
39 39
40pub(crate) type IoMem = kernel::io::mem::IoMem<SZ_2M>;40pub(crate) type IoMem = kernel::io::mem::IoMem<'static, SZ_2M>;
41 41
42pub(crate) struct TyrDrmDriver;42pub(crate) struct TyrDrmDriver;
43 43
@@ -91,12 +91,13 @@ kernel::of_device_table!( · 47 unmodified lines
91 91
92impl platform::Driver for TyrPlatformDriverData {92impl platform::Driver for TyrPlatformDriverData {
93 type IdInfo = ();93 type IdInfo = ();
94 type Data<'bound> = Self;
94 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);95 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
95 96
96 fn probe(97 fn probe<'bound>(
97 pdev: &platform::Device<Core>,98 pdev: &'bound platform::Device<Core<'_>>,
98 _info: Option<&Self::IdInfo>,99 _info: Option<&'bound Self::IdInfo>,
99 ) -> impl PinInit<Self, Error> {100 ) -> impl PinInit<Self, Error> + 'bound {
100 let core_clk = Clk::get(pdev.as_ref(), Some(c"core"))?;101 let core_clk = Clk::get(pdev.as_ref(), Some(c"core"))?;
101 let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c"stacks"))?;102 let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c"stacks"))?;
102 let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c"coregroup"))?;103 let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c"coregroup"))?;
@@ -109,7 +110,7 @@ impl platform::Driver for TyrPlatformDriverData { · 6 unmodified lines
109 let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"sram")?;110 let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"sram")?;
110 111
111 let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;112 let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
112 let iomem = Arc::pin_init(request.iomap_sized::<SZ_2M>(), GFP_KERNEL)?;113 let iomem = Arc::new(request.iomap_sized::<SZ_2M>()?.into_devres()?, GFP_KERNEL)?;
113 114
114 issue_soft_reset(pdev.as_ref(), &iomem)?;115 issue_soft_reset(pdev.as_ref(), &iomem)?;
115 gpu::l2_power_on(pdev.as_ref(), &iomem)?;116 gpu::l2_power_on(pdev.as_ref(), &iomem)?;
drivers/gpu/nova-core/driver.rs+23−15
@@ -3,7 +3,6 @@ · 2 unmodified lines
3use kernel::{3use kernel::{
4 auxiliary,4 auxiliary,
5 device::Core,5 device::Core,
6 devres::Devres,
7 dma::Device,6 dma::Device,
8 dma::DmaMask,7 dma::DmaMask,
9 pci,8 pci,
@@ -21,6 +20,7 @@ use kernel::{ · 11 unmodified lines
21 },20 },
22 Arc,21 Arc,
23 },22 },
23 types::ForLt,
24};24};
25 25
26use crate::gpu::Gpu;26use crate::gpu::Gpu;
@@ -29,13 +29,15 @@ use crate::gpu::Gpu; · 2 unmodified lines
29static AUXILIARY_ID_COUNTER: Atomic<u32> = Atomic::new(0);29static AUXILIARY_ID_COUNTER: Atomic<u32> = Atomic::new(0);
30 30
31#[pin_data]31#[pin_data]
32pub(crate) struct NovaCore {32pub(crate) struct NovaCore<'bound> {
33 #[pin]33 #[pin]
34 pub(crate) gpu: Gpu,34 pub(crate) gpu: Gpu,
35 #[pin]35 #[allow(clippy::type_complexity)]
36 _reg: Devres<auxiliary::Registration>,36 _reg: auxiliary::Registration<'bound, ForLt!(())>,
37}37}
38 38
39pub(crate) struct NovaCoreDriver;
40
39const BAR0_SIZE: usize = SZ_16M;41const BAR0_SIZE: usize = SZ_16M;
40 42
41// For now we only support Ampere which can use up to 47-bit DMA addresses.43// For now we only support Ampere which can use up to 47-bit DMA addresses.
@@ -46,12 +48,12 @@ const BAR0_SIZE: usize = SZ_16M; · 4 unmodified lines
46// DMA addresses. These systems should be quite rare.48// DMA addresses. These systems should be quite rare.
47const GPU_DMA_BITS: u32 = 47;49const GPU_DMA_BITS: u32 = 47;
48 50
49pub(crate) type Bar0 = pci::Bar<BAR0_SIZE>;51pub(crate) type Bar0 = pci::Bar<'static, BAR0_SIZE>;
50 52
51kernel::pci_device_table!(53kernel::pci_device_table!(
52 PCI_TABLE,54 PCI_TABLE,
53 MODULE_PCI_TABLE,55 MODULE_PCI_TABLE,
54 <NovaCore as pci::Driver>::IdInfo,56 <NovaCoreDriver as pci::Driver>::IdInfo,
55 [57 [
56 // Modern NVIDIA GPUs will show up as either VGA or 3D controllers.58 // Modern NVIDIA GPUs will show up as either VGA or 3D controllers.
57 (59 (
@@ -73,11 +75,15 @@ kernel::pci_device_table!( · 15 unmodified lines
73 ]75 ]
74);76);
75 77
76impl pci::Driver for NovaCore {78impl pci::Driver for NovaCoreDriver {
77 type IdInfo = ();79 type IdInfo = ();
80 type Data<'bound> = NovaCore<'bound>;
78 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;81 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
79 82
80 fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {83 fn probe<'bound>(
84 pdev: &'bound pci::Device<Core<'_>>,
85 _info: &'bound Self::IdInfo,
86 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
81 pin_init::pin_init_scope(move || {87 pin_init::pin_init_scope(move || {
82 dev_dbg!(pdev, "Probe Nova Core GPU driver.\n");88 dev_dbg!(pdev, "Probe Nova Core GPU driver.\n");
83 89
@@ -89,26 +95,28 @@ impl pci::Driver for NovaCore { · 5 unmodified lines
89 // other threads of execution.95 // other threads of execution.
90 unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? };96 unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? };
91 97
92 let bar = Arc::pin_init(98 let bar = Arc::new(
93 pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0"),99 pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0")?
100 .into_devres()?,
94 GFP_KERNEL,101 GFP_KERNEL,
95 )?;102 )?;
96 103
97 Ok(try_pin_init!(Self {104 Ok(try_pin_init!(NovaCore {
98 gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?),105 gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?),
99 _reg <- auxiliary::Registration::new(106 _reg: auxiliary::Registration::new(
100 pdev.as_ref(),107 pdev.as_ref(),
101 c"nova-drm",108 c"nova-drm",
102 // TODO[XARR]: Use XArray or perhaps IDA for proper ID allocation/recycling. For109 // TODO[XARR]: Use XArray or perhaps IDA for proper ID allocation/recycling. For
103 // now, use a simple atomic counter that never recycles IDs.110 // now, use a simple atomic counter that never recycles IDs.
104 AUXILIARY_ID_COUNTER.fetch_add(1, Relaxed),111 AUXILIARY_ID_COUNTER.fetch_add(1, Relaxed),
105 crate::MODULE_NAME112 crate::MODULE_NAME,
106 ),113 (),
114 )?,
107 }))115 }))
108 })116 })
109 }117 }
110 118
111 fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {119 fn unbind<'bound>(pdev: &'bound pci::Device<Core<'_>>, this: Pin<&Self::Data<'bound>>) {
112 this.gpu.unbind(pdev.as_ref());120 this.gpu.unbind(pdev.as_ref());
113 }121 }
114}122}
drivers/gpu/nova-core/gpu.rs+1−1
@@ -278,7 +278,7 @@ impl Gpu { · 277 unmodified lines
278 /// Called when the corresponding [`Device`](device::Device) is unbound.278 /// Called when the corresponding [`Device`](device::Device) is unbound.
279 ///279 ///
280 /// Note: This method must only be called from `Driver::unbind`.280 /// Note: This method must only be called from `Driver::unbind`.
281 pub(crate) fn unbind(&self, dev: &device::Device<device::Core>) {281 pub(crate) fn unbind(&self, dev: &device::Device<device::Core<'_>>) {
282 kernel::warn_on!(self282 kernel::warn_on!(self
283 .bar283 .bar
284 .access(dev)284 .access(dev)
drivers/gpu/nova-core/nova_core.rs+1−1
@@ -47,7 +47,7 @@ struct NovaCoreModule { · 46 unmodified lines
47 // Fields are dropped in declaration order, so `_driver` is dropped first,47 // Fields are dropped in declaration order, so `_driver` is dropped first,
48 // then `_debugfs_guard` clears `DEBUGFS_ROOT`.48 // then `_debugfs_guard` clears `DEBUGFS_ROOT`.
49 #[pin]49 #[pin]
50 _driver: Registration<pci::Adapter<driver::NovaCore>>,50 _driver: Registration<pci::Adapter<driver::NovaCoreDriver>>,
51 _debugfs_guard: DebugfsRootGuard,51 _debugfs_guard: DebugfsRootGuard,
52}52}
53 53
drivers/hv/vmbus_drv.c+10−33
@@ -548,34 +548,6 @@ static ssize_t device_show(struct device *dev, · 547 unmodified lines
548}548}
549static DEVICE_ATTR_RO(device);549static DEVICE_ATTR_RO(device);
550 550
551static ssize_t driver_override_store(struct device *dev,
552 struct device_attribute *attr,
553 const char *buf, size_t count)
554{
555 struct hv_device *hv_dev = device_to_hv_device(dev);
556 int ret;
557
558 ret = driver_set_override(dev, &hv_dev->driver_override, buf, count);
559 if (ret)
560 return ret;
561
562 return count;
563}
564
565static ssize_t driver_override_show(struct device *dev,
566 struct device_attribute *attr, char *buf)
567{
568 struct hv_device *hv_dev = device_to_hv_device(dev);
569 ssize_t len;
570
571 device_lock(dev);
572 len = sysfs_emit(buf, "%s\n", hv_dev->driver_override);
573 device_unlock(dev);
574
575 return len;
576}
577static DEVICE_ATTR_RW(driver_override);
578
579/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */551/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
580static struct attribute *vmbus_dev_attrs[] = {552static struct attribute *vmbus_dev_attrs[] = {
581 &dev_attr_id.attr,553 &dev_attr_id.attr,
@@ -606,7 +578,6 @@ static struct attribute *vmbus_dev_attrs[] = { · 24 unmodified lines
606 &dev_attr_channel_vp_mapping.attr,578 &dev_attr_channel_vp_mapping.attr,
607 &dev_attr_vendor.attr,579 &dev_attr_vendor.attr,
608 &dev_attr_device.attr,580 &dev_attr_device.attr,
609 &dev_attr_driver_override.attr,
610 NULL,581 NULL,
611};582};
612 583
@@ -718,9 +689,11 @@ static const struct hv_vmbus_device_id *hv_vmbus_get_id(const struct hv_driver * · 105 unmodified lines
718{689{
719 const guid_t *guid = &dev->dev_type;690 const guid_t *guid = &dev->dev_type;
720 const struct hv_vmbus_device_id *id;691 const struct hv_vmbus_device_id *id;
692 int ret;
721 693
722 /* When driver_override is set, only bind to the matching driver */694 /* If a driver override is set, only bind to the matching driver */
723 if (dev->driver_override && strcmp(dev->driver_override, drv->name))695 ret = device_match_driver_override(&dev->device, &drv->driver);
696 if (ret == 0)
724 return NULL;697 return NULL;
725 698
726 /* Look at the dynamic ids first, before the static ones */699 /* Look at the dynamic ids first, before the static ones */
@@ -728,8 +701,11 @@ static const struct hv_vmbus_device_id *hv_vmbus_get_id(const struct hv_driver * · 1 unmodified line
728 if (!id)701 if (!id)
729 id = hv_vmbus_dev_match(drv->id_table, guid);702 id = hv_vmbus_dev_match(drv->id_table, guid);
730 703
731 /* driver_override will always match, send a dummy id */704 /*
732 if (!id && dev->driver_override)705 * If there's a matching driver override, this function should succeed,
706 * thus return a dummy device ID if no matching ID is found.
707 */
708 if (!id && ret > 0)
733 id = &vmbus_device_null;709 id = &vmbus_device_null;
734 710
735 return id;711 return id;
@@ -1031,6 +1007,7 @@ static const struct dev_pm_ops vmbus_pm = { · 295 unmodified lines
1031/* The one and only one */1007/* The one and only one */
1032static const struct bus_type hv_bus = {1008static const struct bus_type hv_bus = {
1033 .name = "vmbus",1009 .name = "vmbus",
1010 .driver_override = true,
1034 .match = vmbus_match,1011 .match = vmbus_match,
1035 .shutdown = vmbus_shutdown,1012 .shutdown = vmbus_shutdown,
1036 .remove = vmbus_remove,1013 .remove = vmbus_remove,
drivers/hwtracing/coresight/coresight-catu.c+1−1
@@ -706,7 +706,7 @@ static int __init catu_init(void) · 705 unmodified lines
706{706{
707 int ret;707 int ret;
708 708
709 ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver, THIS_MODULE);709 ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver);
710 tmc_etr_set_catu_ops(&etr_catu_buf_ops);710 tmc_etr_set_catu_ops(&etr_catu_buf_ops);
711 return ret;711 return ret;
712}712}
drivers/hwtracing/coresight/coresight-core.c+5−4
@@ -1694,8 +1694,9 @@ static void __exit coresight_exit(void) · 1693 unmodified lines
1694module_init(coresight_init);1694module_init(coresight_init);
1695module_exit(coresight_exit);1695module_exit(coresight_exit);
1696 1696
1697int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,1697int coresight_init_driver_with_owner(const char *drv, struct amba_driver *amba_drv,
1698 struct platform_driver *pdev_drv, struct module *owner)1698 struct platform_driver *pdev_drv, struct module *owner,
1699 const char *mod_name)
1699{1700{
1700 int ret;1701 int ret;
1701 1702
@@ -1705,7 +1706,7 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv, · 3 unmodified lines
1705 return ret;1706 return ret;
1706 }1707 }
1707 1708
1708 ret = __platform_driver_register(pdev_drv, owner);1709 ret = __platform_driver_register(pdev_drv, owner, mod_name);
1709 if (!ret)1710 if (!ret)
1710 return 0;1711 return 0;
1711 1712
@@ -1713,7 +1714,7 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv, · 1 unmodified line
1713 amba_driver_unregister(amba_drv);1714 amba_driver_unregister(amba_drv);
1714 return ret;1715 return ret;
1715}1716}
1716EXPORT_SYMBOL_GPL(coresight_init_driver);1717EXPORT_SYMBOL_GPL(coresight_init_driver_with_owner);
1717 1718
1718void coresight_remove_driver(struct amba_driver *amba_drv,1719void coresight_remove_driver(struct amba_driver *amba_drv,
1719 struct platform_driver *pdev_drv)1720 struct platform_driver *pdev_drv)
drivers/hwtracing/coresight/coresight-cpu-debug.c+1−2
@@ -757,8 +757,7 @@ static struct platform_driver debug_platform_driver = { · 756 unmodified lines
757 757
758static int __init debug_init(void)758static int __init debug_init(void)
759{759{
760 return coresight_init_driver("debug", &debug_driver, &debug_platform_driver,760 return coresight_init_driver("debug", &debug_driver, &debug_platform_driver);
761 THIS_MODULE);
762}761}
763 762
764static void __exit debug_exit(void)763static void __exit debug_exit(void)
drivers/hwtracing/coresight/coresight-funnel.c+1−2
@@ -412,8 +412,7 @@ static struct amba_driver dynamic_funnel_driver = { · 411 unmodified lines
412 412
413static int __init funnel_init(void)413static int __init funnel_init(void)
414{414{
415 return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver,415 return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver);
416 THIS_MODULE);
417}416}
418 417
419static void __exit funnel_exit(void)418static void __exit funnel_exit(void)
drivers/hwtracing/coresight/coresight-replicator.c+1−2
@@ -418,8 +418,7 @@ static struct amba_driver dynamic_replicator_driver = { · 417 unmodified lines
418 418
419static int __init replicator_init(void)419static int __init replicator_init(void)
420{420{
421 return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver,421 return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver);
422 THIS_MODULE);
423}422}
424 423
425static void __exit replicator_exit(void)424static void __exit replicator_exit(void)
drivers/hwtracing/coresight/coresight-stm.c+1−1
@@ -1050,7 +1050,7 @@ static struct platform_driver stm_platform_driver = { · 1049 unmodified lines
1050 1050
1051static int __init stm_init(void)1051static int __init stm_init(void)
1052{1052{
1053 return coresight_init_driver("stm", &stm_driver, &stm_platform_driver, THIS_MODULE);1053 return coresight_init_driver("stm", &stm_driver, &stm_platform_driver);
1054}1054}
1055 1055
1056static void __exit stm_exit(void)1056static void __exit stm_exit(void)
drivers/hwtracing/coresight/coresight-tmc-core.c+1−1
@@ -1046,7 +1046,7 @@ static struct platform_driver tmc_platform_driver = { · 1045 unmodified lines
1046 1046
1047static int __init tmc_init(void)1047static int __init tmc_init(void)
1048{1048{
1049 return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver, THIS_MODULE);1049 return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver);
1050}1050}
1051 1051
1052static void __exit tmc_exit(void)1052static void __exit tmc_exit(void)
drivers/hwtracing/coresight/coresight-tnoc.c+1−1
@@ -344,7 +344,7 @@ static struct platform_driver itnoc_driver = { · 343 unmodified lines
344 344
345static int __init tnoc_init(void)345static int __init tnoc_init(void)
346{346{
347 return coresight_init_driver("tnoc", &trace_noc_driver, &itnoc_driver, THIS_MODULE);347 return coresight_init_driver("tnoc", &trace_noc_driver, &itnoc_driver);
348}348}
349 349
350static void __exit tnoc_exit(void)350static void __exit tnoc_exit(void)
drivers/hwtracing/coresight/coresight-tpdm.c+1−2
@@ -1563,8 +1563,7 @@ static struct platform_driver static_tpdm_driver = { · 1562 unmodified lines
1563 1563
1564static int __init tpdm_init(void)1564static int __init tpdm_init(void)
1565{1565{
1566 return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver,1566 return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver);
1567 THIS_MODULE);
1568}1567}
1569 1568
1570static void __exit tpdm_exit(void)1569static void __exit tpdm_exit(void)
drivers/hwtracing/coresight/coresight-tpiu.c+1−1
@@ -310,7 +310,7 @@ static struct platform_driver tpiu_platform_driver = { · 309 unmodified lines
310 310
311static int __init tpiu_init(void)311static int __init tpiu_init(void)
312{312{
313 return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver, THIS_MODULE);313 return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver);
314}314}
315 315
316static void __exit tpiu_exit(void)316static void __exit tpiu_exit(void)
drivers/i2c/i2c-core-of.c+0−5
@@ -176,11 +176,6 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, · 175 unmodified lines
176 return NOTIFY_OK;176 return NOTIFY_OK;
177 }177 }
178 178
179 /*
180 * Clear the flag before adding the device so that fw_devlink
181 * doesn't skip adding consumers to this device.
182 */
183 fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
184 client = of_i2c_register_device(adap, rd->dn);179 client = of_i2c_register_device(adap, rd->dn);
185 if (IS_ERR(client)) {180 if (IS_ERR(client)) {
186 dev_err(&adap->dev, "failed to create client for '%pOF'\n",181 dev_err(&adap->dev, "failed to create client for '%pOF'\n",
drivers/iommu/dma-iommu.c+6−3
@@ -2149,18 +2149,21 @@ EXPORT_SYMBOL_GPL(dma_iova_destroy); · 2148 unmodified lines
2149 2149
2150void iommu_setup_dma_ops(struct device *dev, struct iommu_domain *domain)2150void iommu_setup_dma_ops(struct device *dev, struct iommu_domain *domain)
2151{2151{
2152 bool dma_iommu;
2153
2152 if (dev_is_pci(dev))2154 if (dev_is_pci(dev))
2153 dev->iommu->pci_32bit_workaround = !iommu_dma_forcedac;2155 dev->iommu->pci_32bit_workaround = !iommu_dma_forcedac;
2154 2156
2155 dev->dma_iommu = iommu_is_dma_domain(domain);2157 dma_iommu = iommu_is_dma_domain(domain);
2156 if (dev->dma_iommu && iommu_dma_init_domain(domain, dev))2158 dev_assign_dma_iommu(dev, dma_iommu);
2159 if (dma_iommu && iommu_dma_init_domain(domain, dev))
2157 goto out_err;2160 goto out_err;
2158 2161
2159 return;2162 return;
2160out_err:2163out_err:
2161 pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",2164 pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
2162 dev_name(dev));2165 dev_name(dev));
2163 dev->dma_iommu = false;2166 dev_clear_dma_iommu(dev);
2164}2167}
2165 2168
2166static bool has_msi_cookie(const struct iommu_domain *domain)2169static bool has_msi_cookie(const struct iommu_domain *domain)
drivers/iommu/iommu.c+2−3
@@ -611,9 +611,8 @@ static void iommu_deinit_device(struct device *dev) · 610 unmodified lines
611 dev->iommu_group = NULL;611 dev->iommu_group = NULL;
612 module_put(ops->owner);612 module_put(ops->owner);
613 dev_iommu_free(dev);613 dev_iommu_free(dev);
614#ifdef CONFIG_IOMMU_DMA614 if (IS_ENABLED(CONFIG_IOMMU_DMA))
615 dev->dma_iommu = false;615 dev_clear_dma_iommu(dev);
616#endif
617}616}
618 617
619static struct iommu_domain *pasid_array_entry_to_domain(void *entry)618static struct iommu_domain *pasid_array_entry_to_domain(void *entry)
drivers/net/pcs/pcs-xpcs-plat.c+1−1
@@ -349,7 +349,7 @@ static int xpcs_plat_init_dev(struct dw_xpcs_plat *pxpcs) · 348 unmodified lines
349 * up later. Make sure DD-core is aware of the OF-node being re-used.349 * up later. Make sure DD-core is aware of the OF-node being re-used.
350 */350 */
351 device_set_node(&mdiodev->dev, fwnode_handle_get(dev_fwnode(dev)));351 device_set_node(&mdiodev->dev, fwnode_handle_get(dev_fwnode(dev)));
352 mdiodev->dev.of_node_reused = true;352 dev_set_of_node_reused(&mdiodev->dev);
353 353
354 /* Pass the data further so the DW XPCS driver core could use it */354 /* Pass the data further so the DW XPCS driver core could use it */
355 mdiodev->dev.platform_data = (void *)device_get_match_data(dev);355 mdiodev->dev.platform_data = (void *)device_get_match_data(dev);
drivers/of/device.c+3−3
@@ -26,7 +26,7 @@ · 25 unmodified lines
26const struct of_device_id *of_match_device(const struct of_device_id *matches,26const struct of_device_id *of_match_device(const struct of_device_id *matches,
27 const struct device *dev)27 const struct device *dev)
28{28{
29 if (!matches || !dev->of_node || dev->of_node_reused)29 if (!matches || !dev->of_node || dev_of_node_reused(dev))
30 return NULL;30 return NULL;
31 return of_match_node(matches, dev->of_node);31 return of_match_node(matches, dev->of_node);
32}32}
@@ -192,7 +192,7 @@ ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) · 159 unmodified lines
192{192{
193 ssize_t sl;193 ssize_t sl;
194 194
195 if (!dev || !dev->of_node || dev->of_node_reused)195 if (!dev || !dev->of_node || dev_of_node_reused(dev))
196 return -ENODEV;196 return -ENODEV;
197 197
198 sl = of_modalias(dev->of_node, str, len - 2);198 sl = of_modalias(dev->of_node, str, len - 2);
@@ -254,7 +254,7 @@ int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env * · 55 unmodified lines
254{254{
255 int sl;255 int sl;
256 256
257 if ((!dev) || (!dev->of_node) || dev->of_node_reused)257 if ((!dev) || (!dev->of_node) || dev_of_node_reused(dev))
258 return -ENODEV;258 return -ENODEV;
259 259
260 /* Devicetree modalias is tricky, we add it in 2 steps */260 /* Devicetree modalias is tricky, we add it in 2 steps */
drivers/of/dynamic.c+0−1
@@ -225,7 +225,6 @@ static void __of_attach_node(struct device_node *np) · 224 unmodified lines
225 np->sibling = np->parent->child;225 np->sibling = np->parent->child;
226 np->parent->child = np;226 np->parent->child = np;
227 of_node_clear_flag(np, OF_DETACHED);227 of_node_clear_flag(np, OF_DETACHED);
228 fwnode_set_flag(&np->fwnode, FWNODE_FLAG_NOT_DEVICE);
229 228
230 raw_spin_unlock_irqrestore(&devtree_lock, flags);229 raw_spin_unlock_irqrestore(&devtree_lock, flags);
231 230
drivers/of/overlay.c+15−0
@@ -185,6 +185,15 @@ static int overlay_notify(struct overlay_changeset *ovcs, · 184 unmodified lines
185 return 0;185 return 0;
186}186}
187 187
188static void overlay_fw_devlink_refresh(struct overlay_changeset *ovcs)
189{
190 for (int i = 0; i < ovcs->count; i++) {
191 struct device_node *np = ovcs->fragments[i].target;
192
193 fw_devlink_refresh_fwnode(of_fwnode_handle(np));
194 }
195}
196
188/*197/*
189 * The values of properties in the "/__symbols__" node are paths in198 * The values of properties in the "/__symbols__" node are paths in
190 * the ovcs->overlay_root. When duplicating the properties, the paths199 * the ovcs->overlay_root. When duplicating the properties, the paths
@@ -951,6 +960,12 @@ static int of_overlay_apply(struct overlay_changeset *ovcs, · 760 unmodified lines
951 pr_err("overlay apply changeset entry notify error %d\n", ret);960 pr_err("overlay apply changeset entry notify error %d\n", ret);
952 /* notify failure is not fatal, continue */961 /* notify failure is not fatal, continue */
953 962
963 /*
964 * Needs to happen after changeset notify to give the listeners a chance
965 * to finish creating all the devices they need to create.
966 */
967 overlay_fw_devlink_refresh(ovcs);
968
954 ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY);969 ret_tmp = overlay_notify(ovcs, OF_OVERLAY_POST_APPLY);
955 if (ret_tmp)970 if (ret_tmp)
956 if (!ret)971 if (!ret)
drivers/of/platform.c+0−5
@@ -744,11 +744,6 @@ static int of_platform_notify(struct notifier_block *nb, · 743 unmodified lines
744 if (of_node_check_flag(rd->dn, OF_POPULATED))744 if (of_node_check_flag(rd->dn, OF_POPULATED))
745 return NOTIFY_OK;745 return NOTIFY_OK;
746 746
747 /*
748 * Clear the flag before adding the device so that fw_devlink
749 * doesn't skip adding consumers to this device.
750 */
751 fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
752 /* pdev_parent may be NULL when no bus platform device */747 /* pdev_parent may be NULL when no bus platform device */
753 pdev_parent = of_find_device_by_node(parent);748 pdev_parent = of_find_device_by_node(parent);
754 pdev = of_platform_device_create(rd->dn, NULL,749 pdev = of_platform_device_create(rd->dn, NULL,
drivers/pci/of.c+1−1
@@ -38,7 +38,7 @@ int pci_set_of_node(struct pci_dev *dev) · 37 unmodified lines
38 struct device *pdev __free(put_device) =38 struct device *pdev __free(put_device) =
39 bus_find_device_by_of_node(&platform_bus_type, node);39 bus_find_device_by_of_node(&platform_bus_type, node);
40 if (pdev)40 if (pdev)
41 dev->bus->dev.of_node_reused = true;41 dev_set_of_node_reused(&dev->bus->dev);
42 42
43 device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));43 device_set_node(&dev->dev, of_fwnode_handle(no_free_ptr(node)));
44 return 0;44 return 0;
drivers/pci/pwrctrl/core.c+1−1
@@ -39,7 +39,7 @@ static int pci_pwrctrl_notify(struct notifier_block *nb, unsigned long action, · 38 unmodified lines
39 * If we got here then the PCI device is the second after the39 * If we got here then the PCI device is the second after the
40 * power control platform device. Mark its OF node as reused.40 * power control platform device. Mark its OF node as reused.
41 */41 */
42 dev->of_node_reused = true;42 dev_set_of_node_reused(dev);
43 break;43 break;
44 }44 }
45 45
drivers/pwm/pwm_th1520.rs+7−6
@@ -92,7 +92,7 @@ struct Th1520WfHw { · 91 unmodified lines
92#[pin_data(PinnedDrop)]92#[pin_data(PinnedDrop)]
93struct Th1520PwmDriverData {93struct Th1520PwmDriverData {
94 #[pin]94 #[pin]
95 iomem: devres::Devres<IoMem<TH1520_PWM_REG_SIZE>>,95 iomem: devres::Devres<IoMem<'static, TH1520_PWM_REG_SIZE>>,
96 clk: Clk,96 clk: Clk,
97}97}
98 98
@@ -316,12 +316,13 @@ kernel::of_device_table!( · 217 unmodified lines
316 316
317impl platform::Driver for Th1520PwmPlatformDriver {317impl platform::Driver for Th1520PwmPlatformDriver {
318 type IdInfo = ();318 type IdInfo = ();
319 type Data<'bound> = Self;
319 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);320 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
320 321
321 fn probe(322 fn probe<'bound>(
322 pdev: &platform::Device<Core>,323 pdev: &'bound platform::Device<Core<'_>>,
323 _id_info: Option<&Self::IdInfo>,324 _id_info: Option<&'bound Self::IdInfo>,
324 ) -> impl PinInit<Self, Error> {325 ) -> impl PinInit<Self, Error> + 'bound {
325 let dev = pdev.as_ref();326 let dev = pdev.as_ref();
326 let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;327 let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
327 328
@@ -351,7 +352,7 @@ impl platform::Driver for Th1520PwmPlatformDriver { · 23 unmodified lines
351 dev,352 dev,
352 TH1520_MAX_PWM_NUM,353 TH1520_MAX_PWM_NUM,
353 try_pin_init!(Th1520PwmDriverData {354 try_pin_init!(Th1520PwmDriverData {
354 iomem <- request.iomap_sized::<TH1520_PWM_REG_SIZE>(),355 iomem <- request.iomap_sized::<TH1520_PWM_REG_SIZE>()?.into_devres(),
355 clk <- clk,356 clk <- clk,
356 }),357 }),
357 )?;358 )?;
drivers/rpmsg/qcom_glink_native.c+0−2
@@ -1626,7 +1626,6 @@ static void qcom_glink_rpdev_release(struct device *dev) · 1625 unmodified lines
1626{1626{
1627 struct rpmsg_device *rpdev = to_rpmsg_device(dev);1627 struct rpmsg_device *rpdev = to_rpmsg_device(dev);
1628 1628
1629 kfree(rpdev->driver_override);
1630 kfree(rpdev);1629 kfree(rpdev);
1631}1630}
1632 1631
@@ -1862,7 +1861,6 @@ static void qcom_glink_device_release(struct device *dev) · 229 unmodified lines
1862 1861
1863 /* Release qcom_glink_alloc_channel() reference */1862 /* Release qcom_glink_alloc_channel() reference */
1864 kref_put(&channel->refcount, qcom_glink_channel_release);1863 kref_put(&channel->refcount, qcom_glink_channel_release);
1865 kfree(rpdev->driver_override);
1866 kfree(rpdev);1864 kfree(rpdev);
1867}1865}
1868 1866
drivers/rpmsg/rpmsg_core.c+7−36
@@ -358,33 +358,6 @@ rpmsg_show_attr(src, src, "0x%x\n"); · 357 unmodified lines
358rpmsg_show_attr(dst, dst, "0x%x\n");358rpmsg_show_attr(dst, dst, "0x%x\n");
359rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");359rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
360 360
361static ssize_t driver_override_store(struct device *dev,
362 struct device_attribute *attr,
363 const char *buf, size_t count)
364{
365 struct rpmsg_device *rpdev = to_rpmsg_device(dev);
366 int ret;
367
368 ret = driver_set_override(dev, &rpdev->driver_override, buf, count);
369 if (ret)
370 return ret;
371
372 return count;
373}
374
375static ssize_t driver_override_show(struct device *dev,
376 struct device_attribute *attr, char *buf)
377{
378 struct rpmsg_device *rpdev = to_rpmsg_device(dev);
379 ssize_t len;
380
381 device_lock(dev);
382 len = sysfs_emit(buf, "%s\n", rpdev->driver_override);
383 device_unlock(dev);
384 return len;
385}
386static DEVICE_ATTR_RW(driver_override);
387
388static ssize_t modalias_show(struct device *dev,361static ssize_t modalias_show(struct device *dev,
389 struct device_attribute *attr, char *buf)362 struct device_attribute *attr, char *buf)
390{363{
@@ -405,7 +378,6 @@ static struct attribute *rpmsg_dev_attrs[] = { · 14 unmodified lines
405 &dev_attr_dst.attr,378 &dev_attr_dst.attr,
406 &dev_attr_src.attr,379 &dev_attr_src.attr,
407 &dev_attr_announce.attr,380 &dev_attr_announce.attr,
408 &dev_attr_driver_override.attr,
409 NULL,381 NULL,
410};382};
411ATTRIBUTE_GROUPS(rpmsg_dev);383ATTRIBUTE_GROUPS(rpmsg_dev);
@@ -424,9 +396,11 @@ static int rpmsg_dev_match(struct device *dev, const struct device_driver *drv) · 12 unmodified lines
424 const struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);396 const struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
425 const struct rpmsg_device_id *ids = rpdrv->id_table;397 const struct rpmsg_device_id *ids = rpdrv->id_table;
426 unsigned int i;398 unsigned int i;
399 int ret;
427 400
428 if (rpdev->driver_override)401 ret = device_match_driver_override(dev, drv);
429 return !strcmp(rpdev->driver_override, drv->name);402 if (ret >= 0)
403 return ret;
430 404
431 if (ids)405 if (ids)
432 for (i = 0; ids[i].name[0]; i++)406 for (i = 0; ids[i].name[0]; i++)
@@ -535,6 +509,7 @@ static const struct bus_type rpmsg_bus = { · 102 unmodified lines
535 .name = "rpmsg",509 .name = "rpmsg",
536 .match = rpmsg_dev_match,510 .match = rpmsg_dev_match,
537 .dev_groups = rpmsg_dev_groups,511 .dev_groups = rpmsg_dev_groups,
512 .driver_override = true,
538 .uevent = rpmsg_uevent,513 .uevent = rpmsg_uevent,
539 .probe = rpmsg_dev_probe,514 .probe = rpmsg_dev_probe,
540 .remove = rpmsg_dev_remove,515 .remove = rpmsg_dev_remove,
@@ -560,11 +535,9 @@ int rpmsg_register_device_override(struct rpmsg_device *rpdev, · 19 unmodified lines
560 535
561 device_initialize(dev);536 device_initialize(dev);
562 if (driver_override) {537 if (driver_override) {
563 ret = driver_set_override(dev, &rpdev->driver_override,538 ret = device_set_driver_override(dev, driver_override);
564 driver_override,
565 strlen(driver_override));
566 if (ret) {539 if (ret) {
567 dev_err(dev, "device_set_override failed: %d\n", ret);540 dev_err(dev, "device_set_driver_override() failed: %d\n", ret);
568 put_device(dev);541 put_device(dev);
569 return ret;542 return ret;
570 }543 }
@@ -573,8 +546,6 @@ int rpmsg_register_device_override(struct rpmsg_device *rpdev, · 2 unmodified lines
573 ret = device_add(dev);546 ret = device_add(dev);
574 if (ret) {547 if (ret) {
575 dev_err(dev, "device_add failed: %d\n", ret);548 dev_err(dev, "device_add failed: %d\n", ret);
576 kfree(rpdev->driver_override);
577 rpdev->driver_override = NULL;
578 put_device(dev);549 put_device(dev);
579 }550 }
580 551
drivers/rpmsg/virtio_rpmsg_bus.c+0−1
@@ -374,7 +374,6 @@ static void virtio_rpmsg_release_device(struct device *dev) · 373 unmodified lines
374 struct rpmsg_device *rpdev = to_rpmsg_device(dev);374 struct rpmsg_device *rpdev = to_rpmsg_device(dev);
375 struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);375 struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
376 376
377 kfree(rpdev->driver_override);
378 kfree(vch);377 kfree(vch);
379}378}
380 379
drivers/soc/tegra/cbb/tegra194-cbb.c+1−1
@@ -2342,7 +2342,7 @@ static int __init tegra194_cbb_init(void) · 2341 unmodified lines
2342{2342{
2343 return platform_driver_register(&tegra194_cbb_driver);2343 return platform_driver_register(&tegra194_cbb_driver);
2344}2344}
2345pure_initcall(tegra194_cbb_init);2345core_initcall(tegra194_cbb_init);
2346 2346
2347static void __exit tegra194_cbb_exit(void)2347static void __exit tegra194_cbb_exit(void)
2348{2348{
drivers/soc/tegra/cbb/tegra234-cbb.c+1−1
@@ -1774,7 +1774,7 @@ static int __init tegra234_cbb_init(void) · 1773 unmodified lines
1774{1774{
1775 return platform_driver_register(&tegra234_cbb_driver);1775 return platform_driver_register(&tegra234_cbb_driver);
1776}1776}
1777pure_initcall(tegra234_cbb_init);1777core_initcall(tegra234_cbb_init);
1778 1778
1779static void __exit tegra234_cbb_exit(void)1779static void __exit tegra234_cbb_exit(void)
1780{1780{
drivers/spi/spi.c+0−5
@@ -5003,11 +5003,6 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action, · 5002 unmodified lines
5003 return NOTIFY_OK;5003 return NOTIFY_OK;
5004 }5004 }
5005 5005
5006 /*
5007 * Clear the flag before adding the device so that fw_devlink
5008 * doesn't skip adding consumers to this device.
5009 */
5010 fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
5011 spi = of_register_spi_device(ctlr, rd->dn);5006 spi = of_register_spi_device(ctlr, rd->dn);
5012 put_device(&ctlr->dev);5007 put_device(&ctlr->dev);
5013 5008
drivers/tty/serial/serial_base_bus.c+1−1
@@ -74,7 +74,7 @@ static int serial_base_device_init(struct uart_port *port, · 73 unmodified lines
74 dev->parent = parent_dev;74 dev->parent = parent_dev;
75 dev->bus = &serial_base_bus_type;75 dev->bus = &serial_base_bus_type;
76 dev->release = release;76 dev->release = release;
77 dev->of_node_reused = true;77 dev_set_of_node_reused(dev);
78 78
79 device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev)));79 device_set_node(dev, fwnode_handle_get(dev_fwnode(parent_dev)));
80 80
drivers/usb/gadget/udc/aspeed-vhub/dev.c+1−1
@@ -593,7 +593,7 @@ int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx) · 592 unmodified lines
593 d->gadget.max_speed = USB_SPEED_HIGH;593 d->gadget.max_speed = USB_SPEED_HIGH;
594 d->gadget.speed = USB_SPEED_UNKNOWN;594 d->gadget.speed = USB_SPEED_UNKNOWN;
595 d->gadget.dev.of_node = vhub->pdev->dev.of_node;595 d->gadget.dev.of_node = vhub->pdev->dev.of_node;
596 d->gadget.dev.of_node_reused = true;596 dev_set_of_node_reused(&d->gadget.dev);
597 597
598 rc = usb_add_gadget_udc(d->port_dev, &d->gadget);598 rc = usb_add_gadget_udc(d->port_dev, &d->gadget);
599 if (rc != 0)599 if (rc != 0)
fs/kernfs/dir.c+7−4
@@ -597,10 +597,13 @@ void kernfs_put(struct kernfs_node *kn) · 596 unmodified lines
597 */597 */
598 parent = kernfs_parent(kn);598 parent = kernfs_parent(kn);
599 599
600 WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS,600 if (atomic_read(&kn->active) != KN_DEACTIVATED_BIAS) {
601 "kernfs_put: %s/%s: released with incorrect active_ref %d\n",601 guard(rcu)();
602 parent ? rcu_dereference(parent->name) : "",602 WARN_ONCE(1,
603 rcu_dereference(kn->name), atomic_read(&kn->active));603 "kernfs_put: %s/%s: released with incorrect active_ref %d\n",
604 parent ? rcu_dereference(parent->name) : "",
605 rcu_dereference(kn->name), atomic_read(&kn->active));
606 }
604 607
605 if (kernfs_type(kn) == KERNFS_LINK)608 if (kernfs_type(kn) == KERNFS_LINK)
606 kernfs_put(kn->symlink.target_kn);609 kernfs_put(kn->symlink.target_kn);
fs/sysfs/file.c+6−3
@@ -70,9 +70,8 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v) · 69 unmodified lines
70 * The code works fine with PAGE_SIZE return but it's likely to70 * The code works fine with PAGE_SIZE return but it's likely to
71 * indicate truncated result or overflow in normal use cases.71 * indicate truncated result or overflow in normal use cases.
72 */72 */
73 if (count >= (ssize_t)PAGE_SIZE) {73 if (count >= PAGE_SIZE) {
74 printk("fill_read_buffer: %pS returned bad count\n",74 WARN(1, "OOB write or bad count %zd at %pS\n", count, ops->show);
75 ops->show);
76 /* Try to struggle along */75 /* Try to struggle along */
77 count = PAGE_SIZE - 1;76 count = PAGE_SIZE - 1;
78 }77 }
@@ -120,6 +119,10 @@ static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf, · 41 unmodified lines
120 len = ops->show(kobj, of->kn->priv, buf);119 len = ops->show(kobj, of->kn->priv, buf);
121 if (len < 0)120 if (len < 0)
122 return len;121 return len;
122 if (len >= (ssize_t)PAGE_SIZE) {
123 printk("fill_read_buffer: %pS returned bad count\n", ops->show);
124 len = PAGE_SIZE - 1;
125 }
123 if (pos) {126 if (pos) {
124 if (len <= pos)127 if (len <= pos)
125 return 0;128 return 0;
include/acpi/acpi_bus.h+11−0
@@ -189,6 +189,10 @@ struct acpi_driver { · 188 unmodified lines
189 * -----------189 * -----------
190 */190 */
191 191
192bool acpi_of_match_device(const struct acpi_device *adev,
193 const struct of_device_id *of_match_table,
194 const struct of_device_id **of_id);
195
192/* Status (_STA) */196/* Status (_STA) */
193 197
194struct acpi_device_status {198struct acpi_device_status {
@@ -996,6 +1000,13 @@ int acpi_scan_add_dep(acpi_handle handle, struct acpi_handle_list *dep_devices); · 801 unmodified lines
996u32 arch_acpi_add_auto_dep(acpi_handle handle);1000u32 arch_acpi_add_auto_dep(acpi_handle handle);
997#else /* CONFIG_ACPI */1001#else /* CONFIG_ACPI */
998 1002
1003static inline bool acpi_of_match_device(const struct acpi_device *adev,
1004 const struct of_device_id *of_match_table,
1005 const struct of_device_id **of_id)
1006{
1007 return false;
1008}
1009
999static inline int register_acpi_bus_type(void *bus) { return 0; }1010static inline int register_acpi_bus_type(void *bus) { return 0; }
1000static inline int unregister_acpi_bus_type(void *bus) { return 0; }1011static inline int unregister_acpi_bus_type(void *bus) { return 0; }
1001 1012
include/linux/amba/bus.h+0−5
@@ -71,11 +71,6 @@ struct amba_device { · 70 unmodified lines
71 unsigned int cid;71 unsigned int cid;
72 struct amba_cs_uci_id uci;72 struct amba_cs_uci_id uci;
73 unsigned int irq[AMBA_NR_IRQS];73 unsigned int irq[AMBA_NR_IRQS];
74 /*
75 * Driver name to force a match. Do not set directly, because core
76 * frees it. Use driver_set_override() to set or clear it.
77 */
78 const char *driver_override;
79};74};
80 75
81struct amba_driver {76struct amba_driver {
include/linux/auxiliary_bus.h+4−0
@@ -62,6 +62,9 @@ · 61 unmodified lines
62 * @sysfs.irqs: irqs xarray contains irq indices which are used by the device,62 * @sysfs.irqs: irqs xarray contains irq indices which are used by the device,
63 * @sysfs.lock: Synchronize irq sysfs creation,63 * @sysfs.lock: Synchronize irq sysfs creation,
64 * @sysfs.irq_dir_exists: whether "irqs" directory exists,64 * @sysfs.irq_dir_exists: whether "irqs" directory exists,
65 * @registration_data_rust: private data owned by the registering (parent)
66 * driver; valid for as long as the device is
67 * registered with the driver core,
65 *68 *
66 * An auxiliary_device represents a part of its parent device's functionality.69 * An auxiliary_device represents a part of its parent device's functionality.
67 * It is given a name that, combined with the registering drivers70 * It is given a name that, combined with the registering drivers
@@ -148,6 +151,7 @@ struct auxiliary_device { · 80 unmodified lines
148 struct mutex lock; /* Synchronize irq sysfs creation */151 struct mutex lock; /* Synchronize irq sysfs creation */
149 bool irq_dir_exists;152 bool irq_dir_exists;
150 } sysfs;153 } sysfs;
154 void *registration_data_rust;
151};155};
152 156
153/**157/**
include/linux/cdx/cdx_bus.h+0−4
@@ -137,9 +137,6 @@ struct cdx_controller { · 136 unmodified lines
137 * @enabled: is this bus enabled137 * @enabled: is this bus enabled
138 * @msi_dev_id: MSI Device ID associated with CDX device138 * @msi_dev_id: MSI Device ID associated with CDX device
139 * @num_msi: Number of MSI's supported by the device139 * @num_msi: Number of MSI's supported by the device
140 * @driver_override: driver name to force a match; do not set directly,
141 * because core frees it; use driver_set_override() to
142 * set or clear it.
143 * @irqchip_lock: lock to synchronize irq/msi configuration140 * @irqchip_lock: lock to synchronize irq/msi configuration
144 * @msi_write_pending: MSI write pending for this device141 * @msi_write_pending: MSI write pending for this device
145 */142 */
@@ -165,7 +162,6 @@ struct cdx_device { · 19 unmodified lines
165 bool enabled;162 bool enabled;
166 u32 msi_dev_id;163 u32 msi_dev_id;
167 u32 num_msi;164 u32 num_msi;
168 const char *driver_override;
169 struct mutex irqchip_lock;165 struct mutex irqchip_lock;
170 bool msi_write_pending;166 bool msi_write_pending;
171};167};
include/linux/coresight.h+5−2
@@ -691,8 +691,11 @@ coresight_find_output_type(struct coresight_platform_data *pdata, · 690 unmodified lines
691 enum coresight_dev_type type,691 enum coresight_dev_type type,
692 union coresight_dev_subtype subtype);692 union coresight_dev_subtype subtype);
693 693
694int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,694int coresight_init_driver_with_owner(const char *drv, struct amba_driver *amba_drv,
695 struct platform_driver *pdev_drv, struct module *owner);695 struct platform_driver *pdev_drv, struct module *owner,
696 const char *mod_name);
697#define coresight_init_driver(drv, amba_drv, pdev_drv) \
698 coresight_init_driver_with_owner(drv, amba_drv, pdev_drv, THIS_MODULE, KBUILD_MODNAME)
696 699
697void coresight_remove_driver(struct amba_driver *amba_drv,700void coresight_remove_driver(struct amba_driver *amba_drv,
698 struct platform_driver *pdev_drv);701 struct platform_driver *pdev_drv);
include/linux/device.h+136−85
@@ -38,7 +38,6 @@ struct device_private; · 37 unmodified lines
38struct device_driver;38struct device_driver;
39struct driver_private;39struct driver_private;
40struct module;40struct module;
41struct class;
42struct subsys_private;41struct subsys_private;
43struct device_node;42struct device_node;
44struct fwnode_handle;43struct fwnode_handle;
@@ -104,10 +103,18 @@ struct device_type { · 59 unmodified lines
104 */103 */
105struct device_attribute {104struct device_attribute {
106 struct attribute attr;105 struct attribute attr;
107 ssize_t (*show)(struct device *dev, struct device_attribute *attr,106 __SYSFS_FUNCTION_ALTERNATIVE(
108 char *buf);107 ssize_t (*show)(struct device *dev, struct device_attribute *attr,
109 ssize_t (*store)(struct device *dev, struct device_attribute *attr,108 char *buf);
110 const char *buf, size_t count);109 ssize_t (*show_const)(struct device *dev, const struct device_attribute *attr,
110 char *buf);
111 );
112 __SYSFS_FUNCTION_ALTERNATIVE(
113 ssize_t (*store)(struct device *dev, struct device_attribute *attr,
114 const char *buf, size_t count);
115 ssize_t (*store_const)(struct device *dev, const struct device_attribute *attr,
116 const char *buf, size_t count);
117 );
111};118};
112 119
113/**120/**
@@ -135,6 +142,77 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, · 21 unmodified lines
135ssize_t device_show_string(struct device *dev, struct device_attribute *attr,142ssize_t device_show_string(struct device *dev, struct device_attribute *attr,
136 char *buf);143 char *buf);
137 144
145typedef ssize_t __device_show_handler_const(struct device *dev, const struct device_attribute *attr,
146 char *buf);
147typedef ssize_t __device_store_handler_const(struct device *dev, const struct device_attribute *attr,
148 const char *buf, size_t count);
149
150#ifdef CONFIG_CFI
151
152#define __DEVICE_ATTR_SHOW_STORE(_show, _store) \
153 .show = _Generic(_show, \
154 __device_show_handler_const * : NULL, \
155 default : _show \
156 ), \
157 .show_const = _Generic(_show, \
158 __device_show_handler_const * : _show, \
159 default : NULL \
160 ), \
161 .store = _Generic(_store, \
162 __device_store_handler_const * : NULL, \
163 default : _store \
164 ), \
165 .store_const = _Generic(_store, \
166 __device_store_handler_const * : _store, \
167 default : NULL \
168 ),
169
170#else
171
172#define __DEVICE_ATTR_SHOW_STORE(_show, _store) \
173 .show = _Generic(_show, \
174 __device_show_handler_const * : (void *)_show, \
175 default : _show \
176 ), \
177 .store = _Generic(_store, \
178 __device_store_handler_const * : (void *)_store, \
179 default : _store \
180 ), \
181
182#endif
183
184
185#define __DEVICE_ATTR(_name, _mode, _show, _store) { \
186 .attr = {.name = __stringify(_name), \
187 .mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \
188 __DEVICE_ATTR_SHOW_STORE(_show, _store) \
189}
190
191#define __DEVICE_ATTR_RO_MODE(_name, _mode) \
192 __DEVICE_ATTR(_name, _mode, _name##_show, NULL)
193
194#define __DEVICE_ATTR_RO(_name) \
195 __DEVICE_ATTR_RO_MODE(_name, 0444)
196
197#define __DEVICE_ATTR_WO(_name) \
198 __DEVICE_ATTR(_name, 0200, NULL, _name##_store)
199
200#define __DEVICE_ATTR_RW_MODE(_name, _mode) \
201 __DEVICE_ATTR(_name, _mode, _name##_show, _name##_store)
202
203#define __DEVICE_ATTR_RW(_name) \
204 __DEVICE_ATTR_RW_MODE(_name, 0644)
205
206#ifdef CONFIG_DEBUG_LOCK_ALLOC
207#define __DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) { \
208 .attr = {.name = __stringify(_name), .mode = _mode, \
209 .ignore_lockdep = true }, \
210 __DEVICE_ATTR_SHOW_STORE(_show, _store) \
211}
212#else
213#define __DEVICE_ATTR_IGNORE_LOCKDEP __DEVICE_ATTR
214#endif
215
138/**216/**
139 * DEVICE_ATTR - Define a device attribute.217 * DEVICE_ATTR - Define a device attribute.
140 * @_name: Attribute name.218 * @_name: Attribute name.
@@ -155,20 +233,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 14 unmodified lines
155 * };233 * };
156 */234 */
157#define DEVICE_ATTR(_name, _mode, _show, _store) \235#define DEVICE_ATTR(_name, _mode, _show, _store) \
158 struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)236 struct device_attribute dev_attr_##_name = __DEVICE_ATTR(_name, _mode, _show, _store)
159
160/**
161 * DEVICE_ATTR_PREALLOC - Define a preallocated device attribute.
162 * @_name: Attribute name.
163 * @_mode: File mode.
164 * @_show: Show handler. Optional, but mandatory if attribute is readable.
165 * @_store: Store handler. Optional, but mandatory if attribute is writable.
166 *
167 * Like DEVICE_ATTR(), but ``SYSFS_PREALLOC`` is set on @_mode.
168 */
169#define DEVICE_ATTR_PREALLOC(_name, _mode, _show, _store) \
170 struct device_attribute dev_attr_##_name = \
171 __ATTR_PREALLOC(_name, _mode, _show, _store)
172 237
173/**238/**
174 * DEVICE_ATTR_RW - Define a read-write device attribute.239 * DEVICE_ATTR_RW - Define a read-write device attribute.
@@ -178,7 +243,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 3 unmodified lines
178 * and @_store is <_name>_store.243 * and @_store is <_name>_store.
179 */244 */
180#define DEVICE_ATTR_RW(_name) \245#define DEVICE_ATTR_RW(_name) \
181 struct device_attribute dev_attr_##_name = __ATTR_RW(_name)246 struct device_attribute dev_attr_##_name = __DEVICE_ATTR_RW(_name)
182 247
183/**248/**
184 * DEVICE_ATTR_ADMIN_RW - Define an admin-only read-write device attribute.249 * DEVICE_ATTR_ADMIN_RW - Define an admin-only read-write device attribute.
@@ -187,7 +252,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 2 unmodified lines
187 * Like DEVICE_ATTR_RW(), but @_mode is 0600.252 * Like DEVICE_ATTR_RW(), but @_mode is 0600.
188 */253 */
189#define DEVICE_ATTR_ADMIN_RW(_name) \254#define DEVICE_ATTR_ADMIN_RW(_name) \
190 struct device_attribute dev_attr_##_name = __ATTR_RW_MODE(_name, 0600)255 struct device_attribute dev_attr_##_name = __DEVICE_ATTR_RW_MODE(_name, 0600)
191 256
192/**257/**
193 * DEVICE_ATTR_RW_NAMED - Define a read-write device attribute with a sysfs name258 * DEVICE_ATTR_RW_NAMED - Define a read-write device attribute with a sysfs name
@@ -201,8 +266,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 7 unmodified lines
201#define DEVICE_ATTR_RW_NAMED(_name, _attrname) \266#define DEVICE_ATTR_RW_NAMED(_name, _attrname) \
202 struct device_attribute dev_attr_##_name = { \267 struct device_attribute dev_attr_##_name = { \
203 .attr = { .name = _attrname, .mode = 0644 }, \268 .attr = { .name = _attrname, .mode = 0644 }, \
204 .show = _name##_show, \269 __DEVICE_ATTR_SHOW_STORE(_name##_show, _name##_store) \
205 .store = _name##_store, \
206 }270 }
207 271
208/**272/**
@@ -212,7 +276,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 3 unmodified lines
212 * Like DEVICE_ATTR(), but @_mode is 0444 and @_show is <_name>_show.276 * Like DEVICE_ATTR(), but @_mode is 0444 and @_show is <_name>_show.
213 */277 */
214#define DEVICE_ATTR_RO(_name) \278#define DEVICE_ATTR_RO(_name) \
215 struct device_attribute dev_attr_##_name = __ATTR_RO(_name)279 struct device_attribute dev_attr_##_name = __DEVICE_ATTR_RO(_name)
216 280
217/**281/**
218 * DEVICE_ATTR_ADMIN_RO - Define an admin-only readable device attribute.282 * DEVICE_ATTR_ADMIN_RO - Define an admin-only readable device attribute.
@@ -221,7 +285,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 2 unmodified lines
221 * Like DEVICE_ATTR_RO(), but @_mode is 0400.285 * Like DEVICE_ATTR_RO(), but @_mode is 0400.
222 */286 */
223#define DEVICE_ATTR_ADMIN_RO(_name) \287#define DEVICE_ATTR_ADMIN_RO(_name) \
224 struct device_attribute dev_attr_##_name = __ATTR_RO_MODE(_name, 0400)288 struct device_attribute dev_attr_##_name = __DEVICE_ATTR_RO_MODE(_name, 0400)
225 289
226/**290/**
227 * DEVICE_ATTR_RO_NAMED - Define a read-only device attribute with a sysfs name291 * DEVICE_ATTR_RO_NAMED - Define a read-only device attribute with a sysfs name
@@ -235,7 +299,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 7 unmodified lines
235#define DEVICE_ATTR_RO_NAMED(_name, _attrname) \299#define DEVICE_ATTR_RO_NAMED(_name, _attrname) \
236 struct device_attribute dev_attr_##_name = { \300 struct device_attribute dev_attr_##_name = { \
237 .attr = { .name = _attrname, .mode = 0444 }, \301 .attr = { .name = _attrname, .mode = 0444 }, \
238 .show = _name##_show, \302 __DEVICE_ATTR_SHOW_STORE(_name##_show, NULL) \
239 }303 }
240 304
241/**305/**
@@ -245,7 +309,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 3 unmodified lines
245 * Like DEVICE_ATTR(), but @_mode is 0200 and @_store is <_name>_store.309 * Like DEVICE_ATTR(), but @_mode is 0200 and @_store is <_name>_store.
246 */310 */
247#define DEVICE_ATTR_WO(_name) \311#define DEVICE_ATTR_WO(_name) \
248 struct device_attribute dev_attr_##_name = __ATTR_WO(_name)312 struct device_attribute dev_attr_##_name = __DEVICE_ATTR_WO(_name)
249 313
250/**314/**
251 * DEVICE_ATTR_WO_NAMED - Define a read-only device attribute with a sysfs name315 * DEVICE_ATTR_WO_NAMED - Define a read-only device attribute with a sysfs name
@@ -259,7 +323,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 7 unmodified lines
259#define DEVICE_ATTR_WO_NAMED(_name, _attrname) \323#define DEVICE_ATTR_WO_NAMED(_name, _attrname) \
260 struct device_attribute dev_attr_##_name = { \324 struct device_attribute dev_attr_##_name = { \
261 .attr = { .name = _attrname, .mode = 0200 }, \325 .attr = { .name = _attrname, .mode = 0200 }, \
262 .store = _name##_store, \326 __DEVICE_ATTR_SHOW_STORE(NULL, _name##_store) \
263 }327 }
264 328
265/**329/**
@@ -273,7 +337,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 7 unmodified lines
273 */337 */
274#define DEVICE_ULONG_ATTR(_name, _mode, _var) \338#define DEVICE_ULONG_ATTR(_name, _mode, _var) \
275 struct dev_ext_attribute dev_attr_##_name = \339 struct dev_ext_attribute dev_attr_##_name = \
276 { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }340 { __DEVICE_ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
277 341
278/**342/**
279 * DEVICE_INT_ATTR - Define a device attribute backed by an int.343 * DEVICE_INT_ATTR - Define a device attribute backed by an int.
@@ -285,7 +349,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 5 unmodified lines
285 */349 */
286#define DEVICE_INT_ATTR(_name, _mode, _var) \350#define DEVICE_INT_ATTR(_name, _mode, _var) \
287 struct dev_ext_attribute dev_attr_##_name = \351 struct dev_ext_attribute dev_attr_##_name = \
288 { __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) }352 { __DEVICE_ATTR(_name, _mode, device_show_int, device_store_int), &(_var) }
289 353
290/**354/**
291 * DEVICE_BOOL_ATTR - Define a device attribute backed by a bool.355 * DEVICE_BOOL_ATTR - Define a device attribute backed by a bool.
@@ -297,7 +361,7 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 5 unmodified lines
297 */361 */
298#define DEVICE_BOOL_ATTR(_name, _mode, _var) \362#define DEVICE_BOOL_ATTR(_name, _mode, _var) \
299 struct dev_ext_attribute dev_attr_##_name = \363 struct dev_ext_attribute dev_attr_##_name = \
300 { __ATTR(_name, _mode, device_show_bool, device_store_bool), &(_var) }364 { __DEVICE_ATTR(_name, _mode, device_show_bool, device_store_bool), &(_var) }
301 365
302/**366/**
303 * DEVICE_STRING_ATTR_RO - Define a device attribute backed by a r/o string.367 * DEVICE_STRING_ATTR_RO - Define a device attribute backed by a r/o string.
@@ -310,11 +374,11 @@ ssize_t device_show_string(struct device *dev, struct device_attribute *attr, · 6 unmodified lines
310 */374 */
311#define DEVICE_STRING_ATTR_RO(_name, _mode, _var) \375#define DEVICE_STRING_ATTR_RO(_name, _mode, _var) \
312 struct dev_ext_attribute dev_attr_##_name = \376 struct dev_ext_attribute dev_attr_##_name = \
313 { __ATTR(_name, (_mode) & ~0222, device_show_string, NULL), (_var) }377 { __DEVICE_ATTR(_name, (_mode) & ~0222, device_show_string, NULL), (_var) }
314 378
315#define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \379#define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \
316 struct device_attribute dev_attr_##_name = \380 struct device_attribute dev_attr_##_name = \
317 __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)381 __DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store)
318 382
319int device_create_file(struct device *device,383int device_create_file(struct device *device,
320 const struct device_attribute *entry);384 const struct device_attribute *entry);
@@ -512,10 +576,40 @@ struct device_physical_location { · 191 unmodified lines
512 *576 *
513 * @DEV_FLAG_READY_TO_PROBE: If set then device_add() has finished enough577 * @DEV_FLAG_READY_TO_PROBE: If set then device_add() has finished enough
514 * initialization that probe could be called.578 * initialization that probe could be called.
579 * @DEV_FLAG_CAN_MATCH: The device has matched with a driver at least once or it
580 * is in a bus (like AMBA) which can't check for matching drivers
581 * until other devices probe successfully.
582 * @DEV_FLAG_DMA_IOMMU: Device is using default IOMMU implementation for DMA and
583 * doesn't rely on dma_ops structure.
584 * @DEV_FLAG_DMA_SKIP_SYNC: DMA sync operations can be skipped for coherent
585 * buffers.
586 * @DEV_FLAG_DMA_OPS_BYPASS: If set then the dma_ops are bypassed for the
587 * streaming DMA operations (->map_* / ->unmap_* / ->sync_*), and
588 * optional (if the coherent mask is large enough) also for dma
589 * allocations. This flag is managed by the dma ops instance from
590 * ->dma_supported.
591 * @DEV_FLAG_STATE_SYNCED: The hardware state of this device has been synced to
592 * match the software state of this device by calling the
593 * driver/bus sync_state() callback.
594 * @DEV_FLAG_DMA_COHERENT: This particular device is dma coherent, even if the
595 * architecture supports non-coherent devices.
596 * @DEV_FLAG_OF_NODE_REUSED: Set if the device-tree node is shared with an
597 * ancestor device.
598 * @DEV_FLAG_OFFLINE_DISABLED: If set, the device is permanently online.
599 * @DEV_FLAG_OFFLINE: Set after successful invocation of bus type's .offline().
515 * @DEV_FLAG_COUNT: Number of defined struct_device_flags.600 * @DEV_FLAG_COUNT: Number of defined struct_device_flags.
516 */601 */
517enum struct_device_flags {602enum struct_device_flags {
518 DEV_FLAG_READY_TO_PROBE = 0,603 DEV_FLAG_READY_TO_PROBE = 0,
604 DEV_FLAG_CAN_MATCH = 1,
605 DEV_FLAG_DMA_IOMMU = 2,
606 DEV_FLAG_DMA_SKIP_SYNC = 3,
607 DEV_FLAG_DMA_OPS_BYPASS = 4,
608 DEV_FLAG_STATE_SYNCED = 5,
609 DEV_FLAG_DMA_COHERENT = 6,
610 DEV_FLAG_OF_NODE_REUSED = 7,
611 DEV_FLAG_OFFLINE_DISABLED = 8,
612 DEV_FLAG_OFFLINE = 9,
519 613
520 DEV_FLAG_COUNT614 DEV_FLAG_COUNT
521};615};
@@ -594,27 +688,6 @@ enum struct_device_flags { · 72 unmodified lines
594 * @removable: Whether the device can be removed from the system. This688 * @removable: Whether the device can be removed from the system. This
595 * should be set by the subsystem / bus driver that discovered689 * should be set by the subsystem / bus driver that discovered
596 * the device.690 * the device.
597 *
598 * @offline_disabled: If set, the device is permanently online.
599 * @offline: Set after successful invocation of bus type's .offline().
600 * @of_node_reused: Set if the device-tree node is shared with an ancestor
601 * device.
602 * @state_synced: The hardware state of this device has been synced to match
603 * the software state of this device by calling the driver/bus
604 * sync_state() callback.
605 * @can_match: The device has matched with a driver at least once or it is in
606 * a bus (like AMBA) which can't check for matching drivers until
607 * other devices probe successfully.
608 * @dma_coherent: this particular device is dma coherent, even if the
609 * architecture supports non-coherent devices.
610 * @dma_ops_bypass: If set to %true then the dma_ops are bypassed for the
611 * streaming DMA operations (->map_* / ->unmap_* / ->sync_*),
612 * and optionall (if the coherent mask is large enough) also
613 * for dma allocations. This flag is managed by the dma ops
614 * instance from ->dma_supported.
615 * @dma_skip_sync: DMA sync operations can be skipped for coherent buffers.
616 * @dma_iommu: Device is using default IOMMU implementation for DMA and
617 * doesn't rely on dma_ops structure.
618 * @flags: DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.691 * @flags: DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.
619 *692 *
620 * At the lowest level, every device in a Linux system is represented by an693 * At the lowest level, every device in a Linux system is represented by an
@@ -719,26 +792,6 @@ struct device { · 98 unmodified lines
719 792
720 enum device_removable removable;793 enum device_removable removable;
721 794
722 bool offline_disabled:1;
723 bool offline:1;
724 bool of_node_reused:1;
725 bool state_synced:1;
726 bool can_match:1;
727#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
728 defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
729 defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
730 bool dma_coherent:1;
731#endif
732#ifdef CONFIG_DMA_OPS_BYPASS
733 bool dma_ops_bypass : 1;
734#endif
735#ifdef CONFIG_DMA_NEED_SYNC
736 bool dma_skip_sync:1;
737#endif
738#ifdef CONFIG_IOMMU_DMA
739 bool dma_iommu:1;
740#endif
741
742 DECLARE_BITMAP(flags, DEV_FLAG_COUNT);795 DECLARE_BITMAP(flags, DEV_FLAG_COUNT);
743};796};
744 797
@@ -765,6 +818,15 @@ static inline bool dev_test_and_set_##accessor_name(struct device *dev) \ · 20 unmodified lines
765}818}
766 819
767__create_dev_flag_accessors(ready_to_probe, DEV_FLAG_READY_TO_PROBE);820__create_dev_flag_accessors(ready_to_probe, DEV_FLAG_READY_TO_PROBE);
821__create_dev_flag_accessors(can_match, DEV_FLAG_CAN_MATCH);
822__create_dev_flag_accessors(dma_iommu, DEV_FLAG_DMA_IOMMU);
823__create_dev_flag_accessors(dma_skip_sync, DEV_FLAG_DMA_SKIP_SYNC);
824__create_dev_flag_accessors(dma_ops_bypass, DEV_FLAG_DMA_OPS_BYPASS);
825__create_dev_flag_accessors(state_synced, DEV_FLAG_STATE_SYNCED);
826__create_dev_flag_accessors(dma_coherent, DEV_FLAG_DMA_COHERENT);
827__create_dev_flag_accessors(of_node_reused, DEV_FLAG_OF_NODE_REUSED);
828__create_dev_flag_accessors(offline_disabled, DEV_FLAG_OFFLINE_DISABLED);
829__create_dev_flag_accessors(offline, DEV_FLAG_OFFLINE);
768 830
769#undef __create_dev_flag_accessors831#undef __create_dev_flag_accessors
770 832
@@ -1063,17 +1125,6 @@ static inline void device_lock_assert(struct device *dev) · 292 unmodified lines
1063 lockdep_assert_held(&dev->mutex);1125 lockdep_assert_held(&dev->mutex);
1064}1126}
1065 1127
1066static inline bool dev_has_sync_state(struct device *dev)
1067{
1068 if (!dev)
1069 return false;
1070 if (dev->driver && dev->driver->sync_state)
1071 return true;
1072 if (dev->bus && dev->bus->sync_state)
1073 return true;
1074 return false;
1075}
1076
1077static inline int dev_set_drv_sync_state(struct device *dev,1128static inline int dev_set_drv_sync_state(struct device *dev,
1078 void (*fn)(struct device *dev))1129 void (*fn)(struct device *dev))
1079{1130{
include/linux/device/bus.h+3−3
@@ -83,9 +83,9 @@ struct fwnode_handle; · 82 unmodified lines
83struct bus_type {83struct bus_type {
84 const char *name;84 const char *name;
85 const char *dev_name;85 const char *dev_name;
86 const struct attribute_group **bus_groups;86 const struct attribute_group *const *bus_groups;
87 const struct attribute_group **dev_groups;87 const struct attribute_group *const *dev_groups;
88 const struct attribute_group **drv_groups;88 const struct attribute_group *const *drv_groups;
89 89
90 int (*match)(struct device *dev, const struct device_driver *drv);90 int (*match)(struct device *dev, const struct device_driver *drv);
91 int (*uevent)(const struct device *dev, struct kobj_uevent_env *env);91 int (*uevent)(const struct device *dev, struct kobj_uevent_env *env);
include/linux/device/class.h+1−1
@@ -34,7 +34,7 @@ struct fwnode_handle; · 33 unmodified lines
34 * @class_release: Called to release this class.34 * @class_release: Called to release this class.
35 * @dev_release: Called to release the device.35 * @dev_release: Called to release the device.
36 * @shutdown_pre: Called at shut-down time before driver shutdown.36 * @shutdown_pre: Called at shut-down time before driver shutdown.
37 * @ns_type: Callbacks so sysfs can detemine namespaces.37 * @ns_type: Callbacks so sysfs can determine namespaces.
38 * @namespace: Namespace of the device belongs to this class.38 * @namespace: Namespace of the device belongs to this class.
39 * @get_ownership: Allows class to specify uid/gid of the sysfs directories39 * @get_ownership: Allows class to specify uid/gid of the sysfs directories
40 * for the devices belonging to the class. Usually tied to40 * for the devices belonging to the class. Usually tied to
include/linux/device/driver.h+4−6
@@ -114,8 +114,8 @@ struct device_driver { · 113 unmodified lines
114 void (*shutdown) (struct device *dev);114 void (*shutdown) (struct device *dev);
115 int (*suspend) (struct device *dev, pm_message_t state);115 int (*suspend) (struct device *dev, pm_message_t state);
116 int (*resume) (struct device *dev);116 int (*resume) (struct device *dev);
117 const struct attribute_group **groups;117 const struct attribute_group *const *groups;
118 const struct attribute_group **dev_groups;118 const struct attribute_group *const *dev_groups;
119 119
120 const struct dev_pm_ops *pm;120 const struct dev_pm_ops *pm;
121 void (*coredump) (struct device *dev);121 void (*coredump) (struct device *dev);
@@ -123,8 +123,8 @@ struct device_driver { · 1 unmodified line
123 struct driver_private *p;123 struct driver_private *p;
124 struct {124 struct {
125 /*125 /*
126 * Called after remove() and after all devres entries have been126 * Called after remove() but before devres entries are released.
127 * processed. This is a Rust only callback.127 * This is a Rust only callback.
128 */128 */
129 void (*post_unbind_rust)(struct device *dev);129 void (*post_unbind_rust)(struct device *dev);
130 } p_cb;130 } p_cb;
@@ -160,8 +160,6 @@ int __must_check driver_create_file(const struct device_driver *driver, · 29 unmodified lines
160void driver_remove_file(const struct device_driver *driver,160void driver_remove_file(const struct device_driver *driver,
161 const struct driver_attribute *attr);161 const struct driver_attribute *attr);
162 162
163int driver_set_override(struct device *dev, const char **override,
164 const char *s, size_t len);
165int __must_check driver_for_each_device(struct device_driver *drv, struct device *start,163int __must_check driver_for_each_device(struct device_driver *drv, struct device *start,
166 void *data, device_iter_t fn);164 void *data, device_iter_t fn);
167struct device *driver_find_device(const struct device_driver *drv,165struct device *driver_find_device(const struct device_driver *drv,
include/linux/dma-map-ops.h+3−3
@@ -225,7 +225,7 @@ int dma_direct_set_offset(struct device *dev, phys_addr_t cpu_start, · 224 unmodified lines
225extern bool dma_default_coherent;225extern bool dma_default_coherent;
226static inline bool dev_is_dma_coherent(struct device *dev)226static inline bool dev_is_dma_coherent(struct device *dev)
227{227{
228 return dev->dma_coherent;228 return dev_dma_coherent(dev);
229}229}
230#else230#else
231#define dma_default_coherent true231#define dma_default_coherent true
@@ -240,8 +240,8 @@ static inline void dma_reset_need_sync(struct device *dev) · 8 unmodified lines
240{240{
241#ifdef CONFIG_DMA_NEED_SYNC241#ifdef CONFIG_DMA_NEED_SYNC
242 /* Reset it only once so that the function can be called on hotpath */242 /* Reset it only once so that the function can be called on hotpath */
243 if (unlikely(dev->dma_skip_sync))243 if (unlikely(dev_dma_skip_sync(dev)))
244 dev->dma_skip_sync = false;244 dev_clear_dma_skip_sync(dev);
245#endif245#endif
246}246}
247 247
include/linux/dma-mapping.h+1−1
@@ -429,7 +429,7 @@ bool __dma_need_sync(struct device *dev, dma_addr_t dma_addr); · 428 unmodified lines
429static inline bool dma_dev_need_sync(const struct device *dev)429static inline bool dma_dev_need_sync(const struct device *dev)
430{430{
431 /* Always call DMA sync operations when debugging is enabled */431 /* Always call DMA sync operations when debugging is enabled */
432 return !dev->dma_skip_sync || IS_ENABLED(CONFIG_DMA_API_DEBUG);432 return !dev_dma_skip_sync(dev) || IS_ENABLED(CONFIG_DMA_API_DEBUG);
433}433}
434 434
435static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,435static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
include/linux/fwnode.h+3−0
@@ -210,8 +210,10 @@ static inline void fwnode_init(struct fwnode_handle *fwnode, · 209 unmodified lines
210{210{
211 fwnode->secondary = NULL;211 fwnode->secondary = NULL;
212 fwnode->ops = ops;212 fwnode->ops = ops;
213 fwnode->dev = NULL;
213 INIT_LIST_HEAD(&fwnode->consumers);214 INIT_LIST_HEAD(&fwnode->consumers);
214 INIT_LIST_HEAD(&fwnode->suppliers);215 INIT_LIST_HEAD(&fwnode->suppliers);
216 fwnode->flags = 0;
215}217}
216 218
217static inline void fwnode_set_flag(struct fwnode_handle *fwnode,219static inline void fwnode_set_flag(struct fwnode_handle *fwnode,
@@ -251,6 +253,7 @@ int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup, · 33 unmodified lines
251 u8 flags);253 u8 flags);
252void fwnode_links_purge(struct fwnode_handle *fwnode);254void fwnode_links_purge(struct fwnode_handle *fwnode);
253void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode);255void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode);
256void fw_devlink_refresh_fwnode(struct fwnode_handle *fwnode);
254bool fw_devlink_is_strict(void);257bool fw_devlink_is_strict(void);
255 258
256#endif259#endif
include/linux/hyperv.h+0−5
@@ -1272,11 +1272,6 @@ struct hv_device { · 1271 unmodified lines
1272 u16 device_id;1272 u16 device_id;
1273 1273
1274 struct device device;1274 struct device device;
1275 /*
1276 * Driver name to force a match. Do not set directly, because core
1277 * frees it. Use driver_set_override() to set or clear it.
1278 */
1279 const char *driver_override;
1280 1275
1281 struct vmbus_channel *channel;1276 struct vmbus_channel *channel;
1282 struct kset *channels_kset;1277 struct kset *channels_kset;
include/linux/iommu-dma.h+2−1
@@ -7,12 +7,13 @@ · 6 unmodified lines
7#ifndef _LINUX_IOMMU_DMA_H7#ifndef _LINUX_IOMMU_DMA_H
8#define _LINUX_IOMMU_DMA_H8#define _LINUX_IOMMU_DMA_H
9 9
10#include <linux/device.h>
10#include <linux/dma-direction.h>11#include <linux/dma-direction.h>
11 12
12#ifdef CONFIG_IOMMU_DMA13#ifdef CONFIG_IOMMU_DMA
13static inline bool use_dma_iommu(struct device *dev)14static inline bool use_dma_iommu(struct device *dev)
14{15{
15 return dev->dma_iommu;16 return dev_dma_iommu(dev);
16}17}
17#else18#else
18static inline bool use_dma_iommu(struct device *dev)19static inline bool use_dma_iommu(struct device *dev)
include/linux/platform_device.h+9−8
@@ -293,18 +293,19 @@ struct platform_driver { · 292 unmodified lines
293 * use a macro to avoid include chaining to get THIS_MODULE293 * use a macro to avoid include chaining to get THIS_MODULE
294 */294 */
295#define platform_driver_register(drv) \295#define platform_driver_register(drv) \
296 __platform_driver_register(drv, THIS_MODULE)296 __platform_driver_register(drv, THIS_MODULE, KBUILD_MODNAME)
297extern int __platform_driver_register(struct platform_driver *,297extern int __platform_driver_register(struct platform_driver *,
298 struct module *);298 struct module *, const char *mod_name);
299extern void platform_driver_unregister(struct platform_driver *);299extern void platform_driver_unregister(struct platform_driver *);
300 300
301/* non-hotpluggable platform devices may use this so that probe() and301/* non-hotpluggable platform devices may use this so that probe() and
302 * its support may live in __init sections, conserving runtime memory.302 * its support may live in __init sections, conserving runtime memory.
303 */303 */
304#define platform_driver_probe(drv, probe) \304#define platform_driver_probe(drv, probe) \
305 __platform_driver_probe(drv, probe, THIS_MODULE)305 __platform_driver_probe(drv, probe, THIS_MODULE, KBUILD_MODNAME)
306extern int __platform_driver_probe(struct platform_driver *driver,306extern int __platform_driver_probe(struct platform_driver *driver,
307 int (*probe)(struct platform_device *), struct module *module);307 int (*probe)(struct platform_device *), struct module *module,
308 const char *mod_name);
308 309
309static inline void *platform_get_drvdata(const struct platform_device *pdev)310static inline void *platform_get_drvdata(const struct platform_device *pdev)
310{311{
@@ -368,19 +369,19 @@ static int __init __platform_driver##_init(void) \ · 57 unmodified lines
368device_initcall(__platform_driver##_init); \369device_initcall(__platform_driver##_init); \
369 370
370#define platform_create_bundle(driver, probe, res, n_res, data, size) \371#define platform_create_bundle(driver, probe, res, n_res, data, size) \
371 __platform_create_bundle(driver, probe, res, n_res, data, size, THIS_MODULE)372 __platform_create_bundle(driver, probe, res, n_res, data, size, THIS_MODULE, KBUILD_MODNAME)
372extern struct platform_device *__platform_create_bundle(373extern struct platform_device *__platform_create_bundle(
373 struct platform_driver *driver, int (*probe)(struct platform_device *),374 struct platform_driver *driver, int (*probe)(struct platform_device *),
374 struct resource *res, unsigned int n_res,375 struct resource *res, unsigned int n_res,
375 const void *data, size_t size, struct module *module);376 const void *data, size_t size, struct module *module, const char *mod_name);
376 377
377int __platform_register_drivers(struct platform_driver * const *drivers,378int __platform_register_drivers(struct platform_driver * const *drivers,
378 unsigned int count, struct module *owner);379 unsigned int count, struct module *owner, const char *mod_name);
379void platform_unregister_drivers(struct platform_driver * const *drivers,380void platform_unregister_drivers(struct platform_driver * const *drivers,
380 unsigned int count);381 unsigned int count);
381 382
382#define platform_register_drivers(drivers, count) \383#define platform_register_drivers(drivers, count) \
383 __platform_register_drivers(drivers, count, THIS_MODULE)384 __platform_register_drivers(drivers, count, THIS_MODULE, KBUILD_MODNAME)
384 385
385#ifdef CONFIG_SUSPEND386#ifdef CONFIG_SUSPEND
386extern int platform_pm_suspend(struct device *dev);387extern int platform_pm_suspend(struct device *dev);
include/linux/property.h+7−1
@@ -471,12 +471,18 @@ struct property_entry { · 470 unmodified lines
471#define PROPERTY_ENTRY_STRING(_name_, _val_) \471#define PROPERTY_ENTRY_STRING(_name_, _val_) \
472 __PROPERTY_ENTRY_ELEMENT(_name_, str, STRING, _val_)472 __PROPERTY_ENTRY_ELEMENT(_name_, str, STRING, _val_)
473 473
474#define __PROPERTY_ENTRY_REF_ARGS(_ref_, ...) \
475 _Generic(_ref_, \
476 const struct software_node_ref_args *: _ref_, \
477 struct software_node_ref_args *: _ref_, \
478 default: &SOFTWARE_NODE_REFERENCE(_ref_, ##__VA_ARGS__))
479
474#define PROPERTY_ENTRY_REF(_name_, _ref_, ...) \480#define PROPERTY_ENTRY_REF(_name_, _ref_, ...) \
475(struct property_entry) { \481(struct property_entry) { \
476 .name = _name_, \482 .name = _name_, \
477 .length = sizeof(struct software_node_ref_args), \483 .length = sizeof(struct software_node_ref_args), \
478 .type = DEV_PROP_REF, \484 .type = DEV_PROP_REF, \
479 { .pointer = &SOFTWARE_NODE_REFERENCE(_ref_, ##__VA_ARGS__), }, \485 { .pointer = __PROPERTY_ENTRY_REF_ARGS(_ref_, ##__VA_ARGS__) }, \
480}486}
481 487
482#define PROPERTY_ENTRY_BOOL(_name_) \488#define PROPERTY_ENTRY_BOOL(_name_) \
include/linux/rpmsg.h+0−4
@@ -41,9 +41,6 @@ struct rpmsg_channel_info { · 40 unmodified lines
41 * rpmsg_device - device that belong to the rpmsg bus41 * rpmsg_device - device that belong to the rpmsg bus
42 * @dev: the device struct42 * @dev: the device struct
43 * @id: device id (used to match between rpmsg drivers and devices)43 * @id: device id (used to match between rpmsg drivers and devices)
44 * @driver_override: driver name to force a match; do not set directly,
45 * because core frees it; use driver_set_override() to
46 * set or clear it.
47 * @src: local address44 * @src: local address
48 * @dst: destination address45 * @dst: destination address
49 * @ept: the rpmsg endpoint of this channel46 * @ept: the rpmsg endpoint of this channel
@@ -53,7 +50,6 @@ struct rpmsg_channel_info { · 3 unmodified lines
53struct rpmsg_device {50struct rpmsg_device {
54 struct device dev;51 struct device dev;
55 struct rpmsg_device_id id;52 struct rpmsg_device_id id;
56 const char *driver_override;
57 u32 src;53 u32 src;
58 u32 dst;54 u32 dst;
59 struct rpmsg_endpoint *ept;55 struct rpmsg_endpoint *ept;
kernel/cpu.c+2−2
@@ -2639,7 +2639,7 @@ static void cpuhp_offline_cpu_device(unsigned int cpu) · 2638 unmodified lines
2639{2639{
2640 struct device *dev = get_cpu_device(cpu);2640 struct device *dev = get_cpu_device(cpu);
2641 2641
2642 dev->offline = true;2642 dev_set_offline(dev);
2643 /* Tell user space about the state change */2643 /* Tell user space about the state change */
2644 kobject_uevent(&dev->kobj, KOBJ_OFFLINE);2644 kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
2645}2645}
@@ -2648,7 +2648,7 @@ static void cpuhp_online_cpu_device(unsigned int cpu) · 2 unmodified lines
2648{2648{
2649 struct device *dev = get_cpu_device(cpu);2649 struct device *dev = get_cpu_device(cpu);
2650 2650
2651 dev->offline = false;2651 dev_clear_offline(dev);
2652 /* Tell user space about the state change */2652 /* Tell user space about the state change */
2653 kobject_uevent(&dev->kobj, KOBJ_ONLINE);2653 kobject_uevent(&dev->kobj, KOBJ_ONLINE);
2654}2654}
kernel/dma/mapping.c+5−7
@@ -126,11 +126,9 @@ static bool dma_go_direct(struct device *dev, dma_addr_t mask, · 125 unmodified lines
126 if (likely(!ops))126 if (likely(!ops))
127 return true;127 return true;
128 128
129#ifdef CONFIG_DMA_OPS_BYPASS129 if (IS_ENABLED(CONFIG_DMA_OPS_BYPASS) && dev_dma_ops_bypass(dev))
130 if (dev->dma_ops_bypass)
131 return min_not_zero(mask, dev->bus_dma_limit) >=130 return min_not_zero(mask, dev->bus_dma_limit) >=
132 dma_direct_get_required_mask(dev);131 dma_direct_get_required_mask(dev);
133#endif
134 return false;132 return false;
135}133}
136 134
@@ -472,7 +470,7 @@ bool dma_need_unmap(struct device *dev) · 335 unmodified lines
472{470{
473 if (!dma_map_direct(dev, get_dma_ops(dev)))471 if (!dma_map_direct(dev, get_dma_ops(dev)))
474 return true;472 return true;
475 if (!dev->dma_skip_sync)473 if (!dev_dma_skip_sync(dev))
476 return true;474 return true;
477 return IS_ENABLED(CONFIG_DMA_API_DEBUG);475 return IS_ENABLED(CONFIG_DMA_API_DEBUG);
478}476}
@@ -488,16 +486,16 @@ static void dma_setup_need_sync(struct device *dev) · 9 unmodified lines
488 * mapping, if any. During the device initialization, it's486 * mapping, if any. During the device initialization, it's
489 * enough to check only for the DMA coherence.487 * enough to check only for the DMA coherence.
490 */488 */
491 dev->dma_skip_sync = dev_is_dma_coherent(dev);489 dev_assign_dma_skip_sync(dev, dev_is_dma_coherent(dev));
492 else if (!ops->sync_single_for_device && !ops->sync_single_for_cpu &&490 else if (!ops->sync_single_for_device && !ops->sync_single_for_cpu &&
493 !ops->sync_sg_for_device && !ops->sync_sg_for_cpu)491 !ops->sync_sg_for_device && !ops->sync_sg_for_cpu)
494 /*492 /*
495 * Synchronization is not possible when none of DMA sync ops493 * Synchronization is not possible when none of DMA sync ops
496 * is set.494 * is set.
497 */495 */
498 dev->dma_skip_sync = true;496 dev_set_dma_skip_sync(dev);
499 else497 else
500 dev->dma_skip_sync = false;498 dev_clear_dma_skip_sync(dev);
501}499}
502#else /* !CONFIG_DMA_NEED_SYNC */500#else /* !CONFIG_DMA_NEED_SYNC */
503static inline void dma_setup_need_sync(struct device *dev) { }501static inline void dma_setup_need_sync(struct device *dev) { }
kernel/params.c+4−4
@@ -942,9 +942,9 @@ const struct kobj_type module_ktype = { · 941 unmodified lines
942/*942/*
943 * param_sysfs_init - create "module" kset943 * param_sysfs_init - create "module" kset
944 *944 *
945 * This must be done before the initramfs is unpacked and945 * This must be done before any driver registration so that when a driver comes
946 * request_module() thus becomes possible, because otherwise the946 * from a built-in module, the driver core can add the module under /sys/module
947 * module load would fail in mod_sysfs_init.947 * and create the associated driver symlinks.
948 */948 */
949static int __init param_sysfs_init(void)949static int __init param_sysfs_init(void)
950{950{
@@ -957,7 +957,7 @@ static int __init param_sysfs_init(void) · 6 unmodified lines
957 957
958 return 0;958 return 0;
959}959}
960subsys_initcall(param_sysfs_init);960pure_initcall(param_sysfs_init);
961 961
962/*962/*
963 * param_sysfs_builtin_init - add sysfs version and parameter963 * param_sysfs_builtin_init - add sysfs version and parameter
mm/hmm.c+1−1
@@ -709,7 +709,7 @@ int hmm_dma_map_alloc(struct device *dev, struct hmm_dma_map *map, · 708 unmodified lines
709 * best approximation to ensure no swiotlb buffering happens.709 * best approximation to ensure no swiotlb buffering happens.
710 */710 */
711#ifdef CONFIG_DMA_NEED_SYNC711#ifdef CONFIG_DMA_NEED_SYNC
712 dma_need_sync = !dev->dma_skip_sync;712 dma_need_sync = !dev_dma_skip_sync(dev);
713#endif /* CONFIG_DMA_NEED_SYNC */713#endif /* CONFIG_DMA_NEED_SYNC */
714 if (dma_need_sync || dma_addressing_limited(dev))714 if (dma_need_sync || dma_addressing_limited(dev))
715 return -EOPNOTSUPP;715 return -EOPNOTSUPP;
rust/Makefile+1−0
@@ -119,6 +119,7 @@ syn-cfgs := \ · 118 unmodified lines
119 feature="parsing" \119 feature="parsing" \
120 feature="printing" \120 feature="printing" \
121 feature="proc-macro" \121 feature="proc-macro" \
122 feature="visit" \
122 feature="visit-mut"123 feature="visit-mut"
123 124
124syn-flags := \125syn-flags := \
rust/helpers/acpi.c+16−0
@@ -0,0 +1,16 @@
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/acpi.h>
4#include <acpi/acpi_bus.h>
5
6__rust_helper bool rust_helper_acpi_of_match_device(const struct acpi_device *adev,
7 const struct of_device_id *of_match_table,
8 const struct of_device_id **of_id)
9{
10 return acpi_of_match_device(adev, of_match_table, of_id);
11}
12
13__rust_helper struct acpi_device *rust_helper_to_acpi_device_node(struct fwnode_handle *fwnode)
14{
15 return to_acpi_device_node(fwnode);
16}
rust/helpers/helpers.c+1−0
@@ -38,6 +38,7 @@ · 37 unmodified lines
38#define __rust_helper __always_inline38#define __rust_helper __always_inline
39#endif39#endif
40 40
41#include "acpi.c"
41#include "atomic.c"42#include "atomic.c"
42#include "atomic_ext.c"43#include "atomic_ext.c"
43#include "auxiliary.c"44#include "auxiliary.c"
rust/kernel/alloc/kbox.rs+39−6
@@ -279,6 +279,27 @@ where · 278 unmodified lines
279 Ok(Box(ptr.cast(), PhantomData))279 Ok(Box(ptr.cast(), PhantomData))
280 }280 }
281 281
282 /// Creates a new zero-initialized `Box<T, A>`.
283 ///
284 /// New memory is allocated with `A` and the [`__GFP_ZERO`] flag. The allocation may fail, in
285 /// which case an error is returned. For ZSTs no memory is allocated.
286 ///
287 /// # Examples
288 ///
289 /// ```
290 /// let b = KBox::<[u8; 128]>::zeroed(GFP_KERNEL)?;
291 /// assert_eq!(*b, [0; 128]);
292 /// # Ok::<(), Error>(())
293 /// ```
294 pub fn zeroed(flags: Flags) -> Result<Self, AllocError>
295 where
296 T: Zeroable,
297 {
298 // SAFETY: `__GFP_ZERO` guarantees the memory is zeroed; `T: Zeroable` guarantees that
299 // all-zeroes is a valid bit pattern for `T`.
300 Ok(unsafe { Self::new_uninit(flags | __GFP_ZERO)?.assume_init() })
301 }
302
282 /// Constructs a new `Pin<Box<T, A>>`. If `T` does not implement [`Unpin`], then `x` will be303 /// Constructs a new `Pin<Box<T, A>>`. If `T` does not implement [`Unpin`], then `x` will be
283 /// pinned in memory and can't be moved.304 /// pinned in memory and can't be moved.
284 #[inline]305 #[inline]
@@ -483,7 +504,7 @@ where · 198 unmodified lines
483 504
484// SAFETY: The pointer returned by `into_foreign` comes from a well aligned505// SAFETY: The pointer returned by `into_foreign` comes from a well aligned
485// pointer to `T` allocated by `A`.506// pointer to `T` allocated by `A`.
486unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A>507unsafe impl<T, A> ForeignOwnable for Box<T, A>
487where508where
488 A: Allocator,509 A: Allocator,
489{510{
@@ -493,8 +514,14 @@ where · 3 unmodified lines
493 core::mem::align_of::<T>()514 core::mem::align_of::<T>()
494 };515 };
495 516
496 type Borrowed<'a> = &'a T;517 type Borrowed<'a>
497 type BorrowedMut<'a> = &'a mut T;518 = &'a T
519 where
520 Self: 'a;
521 type BorrowedMut<'a>
522 = &'a mut T
523 where
524 Self: 'a;
498 525
499 fn into_foreign(self) -> *mut c_void {526 fn into_foreign(self) -> *mut c_void {
500 Box::into_raw(self).cast()527 Box::into_raw(self).cast()
@@ -522,13 +549,19 @@ where · 21 unmodified lines
522 549
523// SAFETY: The pointer returned by `into_foreign` comes from a well aligned550// SAFETY: The pointer returned by `into_foreign` comes from a well aligned
524// pointer to `T` allocated by `A`.551// pointer to `T` allocated by `A`.
525unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>552unsafe impl<T, A> ForeignOwnable for Pin<Box<T, A>>
526where553where
527 A: Allocator,554 A: Allocator,
528{555{
529 const FOREIGN_ALIGN: usize = <Box<T, A> as ForeignOwnable>::FOREIGN_ALIGN;556 const FOREIGN_ALIGN: usize = <Box<T, A> as ForeignOwnable>::FOREIGN_ALIGN;
530 type Borrowed<'a> = Pin<&'a T>;557 type Borrowed<'a>
531 type BorrowedMut<'a> = Pin<&'a mut T>;558 = Pin<&'a T>
559 where
560 Self: 'a;
561 type BorrowedMut<'a>
562 = Pin<&'a mut T>
563 where
564 Self: 'a;
532 565
533 fn into_foreign(self) -> *mut c_void {566 fn into_foreign(self) -> *mut c_void {
534 // SAFETY: We are still treating the box as pinned.567 // SAFETY: We are still treating the box as pinned.
rust/kernel/auxiliary.rs+213−72
@@ -12,19 +12,25 @@ use crate::{ · 11 unmodified lines
12 RawDeviceId,12 RawDeviceId,
13 RawDeviceIdIndex, //13 RawDeviceIdIndex, //
14 },14 },
15 devres::Devres,15
16 driver,16 driver,
17 error::{17 error::{
18 from_result,18 from_result,
19 to_result, //19 to_result, //
20 },20 },
21 prelude::*,21 prelude::*,
22 types::Opaque,22 types::{
23 ForLt,
24 ForeignOwnable,
25 Opaque, //
26 },
23 ThisModule, //27 ThisModule, //
24};28};
25use core::{29use core::{
30 any::TypeId,
26 marker::PhantomData,31 marker::PhantomData,
27 mem::offset_of,32 mem::offset_of,
33 pin::Pin,
28 ptr::{34 ptr::{
29 addr_of_mut,35 addr_of_mut,
30 NonNull, //36 NonNull, //
@@ -36,18 +42,18 @@ pub struct Adapter<T: Driver>(T); · 5 unmodified lines
36 42
37// SAFETY:43// SAFETY:
38// - `bindings::auxiliary_driver` is a C type declared as `repr(C)`.44// - `bindings::auxiliary_driver` is a C type declared as `repr(C)`.
39// - `T` is the type of the driver's device private data.45// - `T::Data` is the type of the driver's device private data.
40// - `struct auxiliary_driver` embeds a `struct device_driver`.46// - `struct auxiliary_driver` embeds a `struct device_driver`.
41// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.47// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
42unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {48unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> {
43 type DriverType = bindings::auxiliary_driver;49 type DriverType = bindings::auxiliary_driver;
44 type DriverData = T;50 type DriverData<'bound> = T::Data<'bound>;
45 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);51 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
46}52}
47 53
48// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if54// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
49// a preceding call to `register` has been successful.55// a preceding call to `register` has been successful.
50unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {56unsafe impl<T: Driver> driver::RegistrationOps for Adapter<T> {
51 unsafe fn register(57 unsafe fn register(
52 adrv: &Opaque<Self::DriverType>,58 adrv: &Opaque<Self::DriverType>,
53 name: &'static CStr,59 name: &'static CStr,
@@ -73,7 +79,7 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { · 19 unmodified lines
73 }79 }
74}80}
75 81
76impl<T: Driver + 'static> Adapter<T> {82impl<T: Driver> Adapter<T> {
77 extern "C" fn probe_callback(83 extern "C" fn probe_callback(
78 adev: *mut bindings::auxiliary_device,84 adev: *mut bindings::auxiliary_device,
79 id: *const bindings::auxiliary_device_id,85 id: *const bindings::auxiliary_device_id,
@@ -82,7 +88,7 @@ impl<T: Driver + 'static> Adapter<T> { · 2 unmodified lines
82 // `struct auxiliary_device`.88 // `struct auxiliary_device`.
83 //89 //
84 // INVARIANT: `adev` is valid for the duration of `probe_callback()`.90 // INVARIANT: `adev` is valid for the duration of `probe_callback()`.
85 let adev = unsafe { &*adev.cast::<Device<device::CoreInternal>>() };91 let adev = unsafe { &*adev.cast::<Device<device::CoreInternal<'_>>>() };
86 92
87 // SAFETY: `DeviceId` is a `#[repr(transparent)`] wrapper of `struct auxiliary_device_id`93 // SAFETY: `DeviceId` is a `#[repr(transparent)`] wrapper of `struct auxiliary_device_id`
88 // and does not add additional invariants, so it's safe to transmute.94 // and does not add additional invariants, so it's safe to transmute.
@@ -102,12 +108,12 @@ impl<T: Driver + 'static> Adapter<T> { · 13 unmodified lines
102 // `struct auxiliary_device`.108 // `struct auxiliary_device`.
103 //109 //
104 // INVARIANT: `adev` is valid for the duration of `remove_callback()`.110 // INVARIANT: `adev` is valid for the duration of `remove_callback()`.
105 let adev = unsafe { &*adev.cast::<Device<device::CoreInternal>>() };111 let adev = unsafe { &*adev.cast::<Device<device::CoreInternal<'_>>>() };
106 112
107 // SAFETY: `remove_callback` is only ever called after a successful call to113 // SAFETY: `remove_callback` is only ever called after a successful call to
108 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called114 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
109 // and stored a `Pin<KBox<T>>`.115 // and stored a `Pin<KBox<T::Data<'_>>>`.
110 let data = unsafe { adev.as_ref().drvdata_borrow::<T>() };116 let data = unsafe { adev.as_ref().drvdata_borrow::<T::Data<'_>>() };
111 117
112 T::unbind(adev, data);118 T::unbind(adev, data);
113 }119 }
@@ -197,13 +203,19 @@ pub trait Driver { · 83 unmodified lines
197 /// type IdInfo: 'static = ();203 /// type IdInfo: 'static = ();
198 type IdInfo: 'static;204 type IdInfo: 'static;
199 205
206 /// The type of the driver's bus device private data.
207 type Data<'bound>: Send + 'bound;
208
200 /// The table of device ids supported by the driver.209 /// The table of device ids supported by the driver.
201 const ID_TABLE: IdTable<Self::IdInfo>;210 const ID_TABLE: IdTable<Self::IdInfo>;
202 211
203 /// Auxiliary driver probe.212 /// Auxiliary driver probe.
204 ///213 ///
205 /// Called when an auxiliary device is matches a corresponding driver.214 /// Called when an auxiliary device is matches a corresponding driver.
206 fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>;215 fn probe<'bound>(
216 dev: &'bound Device<device::Core<'_>>,
217 id_info: &'bound Self::IdInfo,
218 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
207 219
208 /// Auxiliary driver unbind.220 /// Auxiliary driver unbind.
209 ///221 ///
@@ -214,8 +226,8 @@ pub trait Driver { · 4 unmodified lines
214 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O226 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O
215 /// operations to gracefully tear down the device.227 /// operations to gracefully tear down the device.
216 ///228 ///
217 /// Otherwise, release operations for driver resources should be performed in `Self::drop`.229 /// Otherwise, release operations for driver resources should be performed in `Drop`.
218 fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) {230 fn unbind<'bound>(dev: &'bound Device<device::Core<'_>>, this: Pin<&Self::Data<'bound>>) {
219 let _ = (dev, this);231 let _ = (dev, this);
220 }232 }
221}233}
@@ -257,6 +269,49 @@ impl Device<device::Bound> { · 35 unmodified lines
257 // SAFETY: A bound auxiliary device always has a bound parent device.269 // SAFETY: A bound auxiliary device always has a bound parent device.
258 unsafe { parent.as_bound() }270 unsafe { parent.as_bound() }
259 }271 }
272
273 /// Returns a pinned reference to the registration data set by the registering (parent) driver.
274 ///
275 /// `F` is the [`ForLt`](trait@ForLt) encoding of the data type. The returned
276 /// reference has its lifetime shortened from `'static` to `&self`'s borrow lifetime via
277 /// [`ForLt::cast_ref`].
278 ///
279 /// Returns [`EINVAL`] if `F` does not match the type used by the parent driver when calling
280 /// [`Registration::new()`].
281 ///
282 /// Returns [`ENOENT`] if no registration data has been set, e.g. when the device was
283 /// registered by a C driver.
284 pub fn registration_data<F: ForLt + 'static>(&self) -> Result<Pin<&F::Of<'_>>> {
285 // SAFETY: By the type invariant, `self.as_raw()` is a valid `struct auxiliary_device`.
286 let ptr = unsafe { (*self.as_raw()).registration_data_rust };
287 if ptr.is_null() {
288 dev_warn!(
289 self.as_ref(),
290 "No registration data set; parent is not a Rust driver.\n"
291 );
292 return Err(ENOENT);
293 }
294
295 // SAFETY: `ptr` is non-null and was set via `into_foreign()` in `Registration::new()`;
296 // `RegistrationData` is `#[repr(C)]` with `type_id` at offset 0, so reading a `TypeId`
297 // at the start of the allocation is valid regardless of `F`.
298 let type_id = unsafe { ptr.cast::<TypeId>().read() };
299 if type_id != TypeId::of::<F>() {
300 return Err(EINVAL);
301 }
302
303 // SAFETY: The `TypeId` check above confirms that the stored type matches
304 // `F::Of<'static>`; `ptr` remains valid until `Registration::drop()` calls
305 // `from_foreign()`.
306 let wrapper = unsafe { Pin::<KBox<RegistrationData<F::Of<'static>>>>::borrow(ptr) };
307
308 // SAFETY: `data` is a structurally pinned field of `RegistrationData`.
309 let pinned: Pin<&F::Of<'_>> = unsafe { wrapper.map_unchecked(|w| &w.data) };
310
311 // SAFETY: The data was pinned when stored; `cast_ref` only shortens
312 // the lifetime, so the pinning guarantee is preserved.
313 Ok(unsafe { Pin::new_unchecked(F::cast_ref(pinned.get_ref())) })
314 }
260}315}
261 316
262impl Device {317impl Device {
@@ -326,87 +381,173 @@ unsafe impl Send for Device {} · 63 unmodified lines
326// (i.e. `Device<Normal>) are thread safe.381// (i.e. `Device<Normal>) are thread safe.
327unsafe impl Sync for Device {}382unsafe impl Sync for Device {}
328 383
384// SAFETY: Same as `Device<Normal>` -- the underlying `struct auxiliary_device` is the same;
385// `Bound` is a zero-sized type-state marker that does not affect thread safety.
386unsafe impl Sync for Device<device::Bound> {}
387
388/// Wrapper that stores a [`TypeId`] alongside the registration data for runtime type checking.
389#[repr(C)]
390#[pin_data]
391struct RegistrationData<T> {
392 type_id: TypeId,
393 #[pin]
394 data: T,
395}
396
329/// The registration of an auxiliary device.397/// The registration of an auxiliary device.
330///398///
331/// This type represents the registration of a [`struct auxiliary_device`]. When its parent device399/// This type represents the registration of a [`struct auxiliary_device`]. When its parent device
332/// is unbound, the corresponding auxiliary device will be unregistered from the system.400/// is unbound, the corresponding auxiliary device will be unregistered from the system.
333///401///
402/// The type parameter `F` is a [`ForLt`](trait@ForLt) encoding of the registration
403/// data type. For non-lifetime-parameterized types, use [`ForLt!(T)`](macro@ForLt).
404/// The data can be accessed by the auxiliary driver through [`Device::registration_data()`].
405///
334/// # Invariants406/// # Invariants
335///407///
336/// `self.0` always holds a valid pointer to an initialized and registered408/// `self.adev` always holds a valid pointer to an initialized and registered
337/// [`struct auxiliary_device`].409/// [`struct auxiliary_device`] whose `registration_data_rust` field points to a
338pub struct Registration(NonNull<bindings::auxiliary_device>);410/// valid `Pin<KBox<RegistrationData<F::Of<'static>>>>`.
411pub struct Registration<'a, F: ForLt + 'static> {
412 adev: NonNull<bindings::auxiliary_device>,
413 _phantom: PhantomData<F::Of<'a>>,
414}
339 415
340impl Registration {416impl<'a, F: ForLt> Registration<'a, F>
341 /// Create and register a new auxiliary device.417where
342 pub fn new<'a>(418 for<'b> F::Of<'b>: Send + Sync,
419{
420 /// Create and register a new auxiliary device with the given registration data.
421 ///
422 /// The `data` is owned by the registration and can be accessed through the auxiliary device
423 /// via [`Device::registration_data()`].
424 ///
425 /// # Safety
426 ///
427 /// The caller must not `mem::forget()` the returned [`Registration`] or otherwise prevent its
428 /// [`Drop`] implementation from running, since the registration data may contain borrowed
429 /// references that become invalid after `'a` ends.
430 ///
431 /// If the registration data is `'static`, use the safe [`Registration::new()`] instead.
432 pub unsafe fn new_with_lt<E>(
343 parent: &'a device::Device<device::Bound>,433 parent: &'a device::Device<device::Bound>,
344 name: &'a CStr,434 name: &CStr,
345 id: u32,435 id: u32,
346 modname: &'a CStr,436 modname: &CStr,
347 ) -> impl PinInit<Devres<Self>, Error> + 'a {437 data: impl PinInit<F::Of<'a>, E>,
348 pin_init::pin_init_scope(move || {438 ) -> Result<Self>
349 let boxed = KBox::new(Opaque::<bindings::auxiliary_device>::zeroed(), GFP_KERNEL)?;439 where
350 let adev = boxed.get();440 Error: From<E>,
351 441 {
352 // SAFETY: It's safe to set the fields of `struct auxiliary_device` on initialization.442 let data = KBox::pin_init::<Error>(
353 unsafe {443 try_pin_init!(RegistrationData {
354 (*adev).dev.parent = parent.as_raw();444 type_id: TypeId::of::<F>(),
355 (*adev).dev.release = Some(Device::release);445 data <- data,
356 (*adev).name = name.as_char_ptr();446 }),
357 (*adev).id = id;447 GFP_KERNEL,
358 }448 )?;
359 449
360 // SAFETY: `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`,450 // SAFETY: `'a` is invariant (via `Registration`'s `PhantomData`). Lifetimes do not
361 // which has not been initialized yet.451 // affect layout, so RegistrationData<F::Of<'a>> and RegistrationData<F::Of<'static>>
362 unsafe { bindings::auxiliary_device_init(adev) };452 // have identical representation.
363 453 let data: Pin<KBox<RegistrationData<F::Of<'static>>>> =
364 // Now that `adev` is initialized, leak the `Box`; the corresponding memory will be454 unsafe { core::mem::transmute(data) };
365 // freed by `Device::release` when the last reference to the `struct auxiliary_device`455
366 // is dropped.456 let boxed: KBox<Opaque<bindings::auxiliary_device>> = KBox::zeroed(GFP_KERNEL)?;
367 let _ = KBox::into_raw(boxed);457 let adev = boxed.get();
368 458
369 // SAFETY:459 // SAFETY: It's safe to set the fields of `struct auxiliary_device` on initialization.
370 // - `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`, which460 unsafe {
371 // has been initialized,461 (*adev).dev.parent = parent.as_raw();
372 // - `modname.as_char_ptr()` is a NULL terminated string.462 (*adev).dev.release = Some(Device::release);
373 let ret = unsafe { bindings::__auxiliary_device_add(adev, modname.as_char_ptr()) };463 (*adev).name = name.as_char_ptr();
374 if ret != 0 {464 (*adev).id = id;
375 // SAFETY: `adev` is guaranteed to be a valid pointer to a465 (*adev).registration_data_rust = data.into_foreign();
376 // `struct auxiliary_device`, which has been initialized.466 }
377 unsafe { bindings::auxiliary_device_uninit(adev) };467
378 468 // SAFETY: `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`,
379 return Err(Error::from_errno(ret));469 // which has not been initialized yet.
380 }470 unsafe { bindings::auxiliary_device_init(adev) };
381 471
382 // INVARIANT: The device will remain registered until `auxiliary_device_delete()` is472 // Now that `adev` is initialized, leak the `Box`; the corresponding memory will be
383 // called, which happens in `Self::drop()`.473 // freed by `Device::release` when the last reference to the `struct auxiliary_device`
384 Ok(Devres::new(474 // is dropped.
385 parent,475 let _ = KBox::into_raw(boxed);
386 // SAFETY: `adev` is guaranteed to be non-null, since the `KBox` was allocated476
387 // successfully.477 // SAFETY:
388 Self(unsafe { NonNull::new_unchecked(adev) }),478 // - `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`, which
389 ))479 // has been initialized,
480 // - `modname.as_char_ptr()` is a NULL terminated string.
481 let ret = unsafe { bindings::__auxiliary_device_add(adev, modname.as_char_ptr()) };
482 if ret != 0 {
483 // SAFETY: `registration_data` was set above via `into_foreign()`.
484 drop(unsafe {
485 Pin::<KBox<RegistrationData<F::Of<'static>>>>::from_foreign(
486 (*adev).registration_data_rust,
487 )
488 });
489
490 // SAFETY: `adev` is guaranteed to be a valid pointer to a
491 // `struct auxiliary_device`, which has been initialized.
492 unsafe { bindings::auxiliary_device_uninit(adev) };
493
494 return Err(Error::from_errno(ret));
495 }
496
497 // INVARIANT: The device will remain registered until `auxiliary_device_delete()` is
498 // called, which happens in `Self::drop()`.
499 Ok(Self {
500 // SAFETY: `adev` is guaranteed to be non-null, since the `KBox` was allocated
501 // successfully.
502 adev: unsafe { NonNull::new_unchecked(adev) },
503 _phantom: PhantomData,
390 })504 })
391 }505 }
506
507 /// Create and register a new auxiliary device with `'static` registration data.
508 ///
509 /// Safe variant of [`Registration::new_with_lt()`] for registration data that does not contain
510 /// borrowed references.
511 pub fn new<E>(
512 parent: &'a device::Device<device::Bound>,
513 name: &CStr,
514 id: u32,
515 modname: &CStr,
516 data: impl PinInit<F::Of<'a>, E>,
517 ) -> Result<Self>
518 where
519 F::Of<'a>: 'static,
520 Error: From<E>,
521 {
522 // SAFETY: `F::Of<'a>: 'static` guarantees the data contains no borrowed references,
523 // so forgetting the `Registration` cannot cause use-after-free.
524 unsafe { Self::new_with_lt(parent, name, id, modname, data) }
525 }
392}526}
393 527
394impl Drop for Registration {528impl<F: ForLt> Drop for Registration<'_, F> {
395 fn drop(&mut self) {529 fn drop(&mut self) {
396 // SAFETY: By the type invariant of `Self`, `self.0.as_ptr()` is a valid registered530 // SAFETY: By the type invariant of `Self`, `self.adev.as_ptr()` is a valid registered
397 // `struct auxiliary_device`.531 // `struct auxiliary_device`.
398 unsafe { bindings::auxiliary_device_delete(self.0.as_ptr()) };532 unsafe { bindings::auxiliary_device_delete(self.adev.as_ptr()) };
533
534 // SAFETY: `registration_data` was set in `new()` via `into_foreign()`.
535 drop(unsafe {
536 Pin::<KBox<RegistrationData<F::Of<'static>>>>::from_foreign(
537 (*self.adev.as_ptr()).registration_data_rust,
538 )
539 });
399 540
400 // This drops the reference we acquired through `auxiliary_device_init()`.541 // This drops the reference we acquired through `auxiliary_device_init()`.
401 //542 //
402 // SAFETY: By the type invariant of `Self`, `self.0.as_ptr()` is a valid registered543 // SAFETY: By the type invariant of `Self`, `self.adev.as_ptr()` is a valid registered
403 // `struct auxiliary_device`.544 // `struct auxiliary_device`.
404 unsafe { bindings::auxiliary_device_uninit(self.0.as_ptr()) };545 unsafe { bindings::auxiliary_device_uninit(self.adev.as_ptr()) };
405 }546 }
406}547}
407 548
408// SAFETY: A `Registration` of a `struct auxiliary_device` can be released from any thread.549// SAFETY: A `Registration` of a `struct auxiliary_device` can be released from any thread.
409unsafe impl Send for Registration {}550unsafe impl<F: ForLt> Send for Registration<'_, F> where for<'a> F::Of<'a>: Send {}
410 551
411// SAFETY: `Registration` does not expose any methods or fields that need synchronization.552// SAFETY: `Registration` does not expose any methods or fields that need synchronization.
412unsafe impl Sync for Registration {}553unsafe impl<F: ForLt> Sync for Registration<'_, F> where for<'a> F::Of<'a>: Send {}
rust/kernel/cpufreq.rs+5−4
@@ -888,12 +888,13 @@ pub trait Driver { · 887 unmodified lines
888///888///
889/// impl platform::Driver for SampleDriver {889/// impl platform::Driver for SampleDriver {
890/// type IdInfo = ();890/// type IdInfo = ();
891/// type Data<'bound> = Self;
891/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;892/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
892///893///
893/// fn probe(894/// fn probe<'bound>(
894/// pdev: &platform::Device<Core>,895/// pdev: &'bound platform::Device<Core<'_>>,
895/// _id_info: Option<&Self::IdInfo>,896/// _id_info: Option<&'bound Self::IdInfo>,
896/// ) -> impl PinInit<Self, Error> {897/// ) -> impl PinInit<Self, Error> + 'bound {
897/// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?;898/// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?;
898/// Ok(Self {})899/// Ok(Self {})
899/// }900/// }
rust/kernel/device.rs+46−75
@@ -15,16 +15,12 @@ use crate::{ · 14 unmodified lines
15 }, //15 }, //
16};16};
17use core::{17use core::{
18 any::TypeId,
19 marker::PhantomData,18 marker::PhantomData,
20 ptr, //19 ptr, //
21};20};
22 21
23pub mod property;22pub mod property;
24 23
25// Assert that we can `read()` / `write()` a `TypeId` instance from / into `struct driver_type`.
26static_assert!(core::mem::size_of::<bindings::driver_type>() >= core::mem::size_of::<TypeId>());
27
28/// The core representation of a device in the kernel's driver model.24/// The core representation of a device in the kernel's driver model.
29///25///
30/// This structure represents the Rust abstraction for a C `struct device`. A [`Device`] can either26/// This structure represents the Rust abstraction for a C `struct device`. A [`Device`] can either
@@ -205,30 +201,13 @@ impl Device { · 174 unmodified lines
205 }201 }
206}202}
207 203
208impl Device<CoreInternal> {204impl<'a> Device<CoreInternal<'a>> {
209 fn set_type_id<T: 'static>(&self) {
210 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
211 let private = unsafe { (*self.as_raw()).p };
212
213 // SAFETY: For a bound device (implied by the `CoreInternal` device context), `private` is
214 // guaranteed to be a valid pointer to a `struct device_private`.
215 let driver_type = unsafe { &raw mut (*private).driver_type };
216
217 // SAFETY: `driver_type` is valid for (unaligned) writes of a `TypeId`.
218 unsafe {
219 driver_type
220 .cast::<TypeId>()
221 .write_unaligned(TypeId::of::<T>())
222 };
223 }
224
225 /// Store a pointer to the bound driver's private data.205 /// Store a pointer to the bound driver's private data.
226 pub fn set_drvdata<T: 'static>(&self, data: impl PinInit<T, Error>) -> Result {206 pub fn set_drvdata<T>(&self, data: impl PinInit<T, Error>) -> Result {
227 let data = KBox::pin_init(data, GFP_KERNEL)?;207 let data = KBox::pin_init(data, GFP_KERNEL)?;
228 208
229 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.209 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
230 unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) };210 unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) };
231 self.set_type_id::<T>();
232 211
233 Ok(())212 Ok(())
234 }213 }
@@ -239,7 +218,7 @@ impl Device<CoreInternal> { · 4 unmodified lines
239 ///218 ///
240 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by219 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by
241 /// [`Device::set_drvdata`].220 /// [`Device::set_drvdata`].
242 pub(crate) unsafe fn drvdata_obtain<T: 'static>(&self) -> Option<Pin<KBox<T>>> {221 pub(crate) unsafe fn drvdata_obtain<T>(&self) -> Option<Pin<KBox<T>>> {
243 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.222 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
244 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };223 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };
245 224
@@ -265,7 +244,7 @@ impl Device<CoreInternal> { · 19 unmodified lines
265 /// device is fully unbound.244 /// device is fully unbound.
266 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by245 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by
267 /// [`Device::set_drvdata`].246 /// [`Device::set_drvdata`].
268 pub unsafe fn drvdata_borrow<T: 'static>(&self) -> Pin<&T> {247 pub unsafe fn drvdata_borrow<T>(&self) -> Pin<&T> {
269 // SAFETY: `drvdata_unchecked()` has the exact same safety requirements as the ones248 // SAFETY: `drvdata_unchecked()` has the exact same safety requirements as the ones
270 // required by this method.249 // required by this method.
271 unsafe { self.drvdata_unchecked() }250 unsafe { self.drvdata_unchecked() }
@@ -281,7 +260,7 @@ impl Device<Bound> { · 9 unmodified lines
281 /// the device is fully unbound.260 /// the device is fully unbound.
282 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by261 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by
283 /// [`Device::set_drvdata`].262 /// [`Device::set_drvdata`].
284 unsafe fn drvdata_unchecked<T: 'static>(&self) -> Pin<&T> {263 unsafe fn drvdata_unchecked<T>(&self) -> Pin<&T> {
285 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.264 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
286 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };265 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };
287 266
@@ -292,45 +271,6 @@ impl Device<Bound> { · 4 unmodified lines
292 // in `into_foreign()`.271 // in `into_foreign()`.
293 unsafe { Pin::<KBox<T>>::borrow(ptr.cast()) }272 unsafe { Pin::<KBox<T>>::borrow(ptr.cast()) }
294 }273 }
295
296 fn match_type_id<T: 'static>(&self) -> Result {
297 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
298 let private = unsafe { (*self.as_raw()).p };
299
300 // SAFETY: For a bound device, `private` is guaranteed to be a valid pointer to a
301 // `struct device_private`.
302 let driver_type = unsafe { &raw mut (*private).driver_type };
303
304 // SAFETY:
305 // - `driver_type` is valid for (unaligned) reads of a `TypeId`.
306 // - A bound device guarantees that `driver_type` contains a valid `TypeId` value.
307 let type_id = unsafe { driver_type.cast::<TypeId>().read_unaligned() };
308
309 if type_id != TypeId::of::<T>() {
310 return Err(EINVAL);
311 }
312
313 Ok(())
314 }
315
316 /// Access a driver's private data.
317 ///
318 /// Returns a pinned reference to the driver's private data or [`EINVAL`] if it doesn't match
319 /// the asserted type `T`.
320 pub fn drvdata<T: 'static>(&self) -> Result<Pin<&T>> {
321 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
322 if unsafe { bindings::dev_get_drvdata(self.as_raw()) }.is_null() {
323 return Err(ENOENT);
324 }
325
326 self.match_type_id::<T>()?;
327
328 // SAFETY:
329 // - The above check of `dev_get_drvdata()` guarantees that we are called after
330 // `set_drvdata()`.
331 // - We've just checked that the type of the driver's private data is in fact `T`.
332 Ok(unsafe { self.drvdata_unchecked() })
333 }
334}274}
335 275
336impl<Ctx: DeviceContext> Device<Ctx> {276impl<Ctx: DeviceContext> Device<Ctx> {
@@ -527,6 +467,10 @@ unsafe impl Send for Device {} · 190 unmodified lines
527// synchronization in `struct device`.467// synchronization in `struct device`.
528unsafe impl Sync for Device {}468unsafe impl Sync for Device {}
529 469
470// SAFETY: Same as `Device<Normal>` -- the underlying `struct device` is the same; `Bound` is a
471// zero-sized type-state marker that does not affect thread safety.
472unsafe impl Sync for Device<Bound> {}
473
530/// Marker trait for the context or scope of a bus specific device.474/// Marker trait for the context or scope of a bus specific device.
531///475///
532/// [`DeviceContext`] is a marker trait for types representing the context of a bus specific476/// [`DeviceContext`] is a marker trait for types representing the context of a bus specific
@@ -567,7 +511,7 @@ pub struct Normal; · 34 unmodified lines
567/// callback it appears in. It is intended to be used for synchronization purposes. Bus device511/// callback it appears in. It is intended to be used for synchronization purposes. Bus device
568/// implementations can implement methods for [`Device<Core>`], such that they can only be called512/// implementations can implement methods for [`Device<Core>`], such that they can only be called
569/// from bus callbacks.513/// from bus callbacks.
570pub struct Core;514pub struct Core<'a>(PhantomData<&'a ()>);
571 515
572/// Semantically the same as [`Core`], but reserved for internal usage of the corresponding bus516/// Semantically the same as [`Core`], but reserved for internal usage of the corresponding bus
573/// abstraction.517/// abstraction.
@@ -578,7 +522,7 @@ pub struct Core; · 4 unmodified lines
578///522///
579/// This context mainly exists to share generic [`Device`] infrastructure that should only be called523/// This context mainly exists to share generic [`Device`] infrastructure that should only be called
580/// from bus callbacks with bus abstractions, but without making them accessible for drivers.524/// from bus callbacks with bus abstractions, but without making them accessible for drivers.
581pub struct CoreInternal;525pub struct CoreInternal<'a>(PhantomData<&'a ()>);
582 526
583/// The [`Bound`] context is the [`DeviceContext`] of a bus specific device when it is guaranteed to527/// The [`Bound`] context is the [`DeviceContext`] of a bus specific device when it is guaranteed to
584/// be bound to a driver.528/// be bound to a driver.
@@ -602,14 +546,14 @@ mod private { · 17 unmodified lines
602 pub trait Sealed {}546 pub trait Sealed {}
603 547
604 impl Sealed for super::Bound {}548 impl Sealed for super::Bound {}
605 impl Sealed for super::Core {}549 impl<'a> Sealed for super::Core<'a> {}
606 impl Sealed for super::CoreInternal {}550 impl<'a> Sealed for super::CoreInternal<'a> {}
607 impl Sealed for super::Normal {}551 impl Sealed for super::Normal {}
608}552}
609 553
610impl DeviceContext for Bound {}554impl DeviceContext for Bound {}
611impl DeviceContext for Core {}555impl<'a> DeviceContext for Core<'a> {}
612impl DeviceContext for CoreInternal {}556impl<'a> DeviceContext for CoreInternal<'a> {}
613impl DeviceContext for Normal {}557impl DeviceContext for Normal {}
614 558
615impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx> {559impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx> {
@@ -659,6 +603,22 @@ pub unsafe trait AsBusDevice<Ctx: DeviceContext>: AsRef<Device<Ctx>> { · 43 unmodified lines
659#[doc(hidden)]603#[doc(hidden)]
660#[macro_export]604#[macro_export]
661macro_rules! __impl_device_context_deref {605macro_rules! __impl_device_context_deref {
606 (unsafe { $device:ident, <$lt:lifetime> $src:ty => $dst:ty }) => {
607 impl<$lt> ::core::ops::Deref for $device<$src> {
608 type Target = $device<$dst>;
609
610 fn deref(&self) -> &Self::Target {
611 let ptr: *const Self = self;
612
613 // CAST: `$device<$src>` and `$device<$dst>` transparently wrap the same type by the
614 // safety requirement of the macro.
615 let ptr = ptr.cast::<Self::Target>();
616
617 // SAFETY: `ptr` was derived from `&self`.
618 unsafe { &*ptr }
619 }
620 }
621 };
662 (unsafe { $device:ident, $src:ty => $dst:ty }) => {622 (unsafe { $device:ident, $src:ty => $dst:ty }) => {
663 impl ::core::ops::Deref for $device<$src> {623 impl ::core::ops::Deref for $device<$src> {
664 type Target = $device<$dst>;624 type Target = $device<$dst>;
@@ -691,14 +651,14 @@ macro_rules! impl_device_context_deref { · 26 unmodified lines
691 // `__impl_device_context_deref!`.651 // `__impl_device_context_deref!`.
692 ::kernel::__impl_device_context_deref!(unsafe {652 ::kernel::__impl_device_context_deref!(unsafe {
693 $device,653 $device,
694 $crate::device::CoreInternal => $crate::device::Core654 <'a> $crate::device::CoreInternal<'a> => $crate::device::Core<'a>
695 });655 });
696 656
697 // SAFETY: This macro has the exact same safety requirement as657 // SAFETY: This macro has the exact same safety requirement as
698 // `__impl_device_context_deref!`.658 // `__impl_device_context_deref!`.
699 ::kernel::__impl_device_context_deref!(unsafe {659 ::kernel::__impl_device_context_deref!(unsafe {
700 $device,660 $device,
701 $crate::device::Core => $crate::device::Bound661 <'a> $crate::device::Core<'a> => $crate::device::Bound
702 });662 });
703 663
704 // SAFETY: This macro has the exact same safety requirement as664 // SAFETY: This macro has the exact same safety requirement as
@@ -713,6 +673,13 @@ macro_rules! impl_device_context_deref { · 8 unmodified lines
713#[doc(hidden)]673#[doc(hidden)]
714#[macro_export]674#[macro_export]
715macro_rules! __impl_device_context_into_aref {675macro_rules! __impl_device_context_into_aref {
676 (<$lt:lifetime> $src:ty, $device:tt) => {
677 impl<$lt> ::core::convert::From<&$device<$src>> for $crate::sync::aref::ARef<$device> {
678 fn from(dev: &$device<$src>) -> Self {
679 (&**dev).into()
680 }
681 }
682 };
716 ($src:ty, $device:tt) => {683 ($src:ty, $device:tt) => {
717 impl ::core::convert::From<&$device<$src>> for $crate::sync::aref::ARef<$device> {684 impl ::core::convert::From<&$device<$src>> for $crate::sync::aref::ARef<$device> {
718 fn from(dev: &$device<$src>) -> Self {685 fn from(dev: &$device<$src>) -> Self {
@@ -727,8 +694,12 @@ macro_rules! __impl_device_context_into_aref { · 8 unmodified lines
727#[macro_export]694#[macro_export]
728macro_rules! impl_device_context_into_aref {695macro_rules! impl_device_context_into_aref {
729 ($device:tt) => {696 ($device:tt) => {
730 ::kernel::__impl_device_context_into_aref!($crate::device::CoreInternal, $device);697 ::kernel::__impl_device_context_into_aref!(
731 ::kernel::__impl_device_context_into_aref!($crate::device::Core, $device);698 <'a> $crate::device::CoreInternal<'a>, $device
699 );
700 ::kernel::__impl_device_context_into_aref!(
701 <'a> $crate::device::Core<'a>, $device
702 );
732 ::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device);703 ::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device);
733 };704 };
734}705}
rust/kernel/devres.rs+4−4
@@ -122,7 +122,7 @@ struct Inner<T> { · 121 unmodified lines
122/// # Ok(())122/// # Ok(())
123/// # }123/// # }
124/// ```124/// ```
125pub struct Devres<T: Send> {125pub struct Devres<T: Send + 'static> {
126 dev: ARef<Device>,126 dev: ARef<Device>,
127 inner: Arc<Inner<T>>,127 inner: Arc<Inner<T>>,
128}128}
@@ -184,7 +184,7 @@ mod base { · 55 unmodified lines
184 }184 }
185}185}
186 186
187impl<T: Send> Devres<T> {187impl<T: Send + 'static> Devres<T> {
188 /// Creates a new [`Devres`] instance of the given `data`.188 /// Creates a new [`Devres`] instance of the given `data`.
189 ///189 ///
190 /// The `data` encapsulated within the returned `Devres` instance' `data` will be190 /// The `data` encapsulated within the returned `Devres` instance' `data` will be
@@ -304,7 +304,7 @@ impl<T: Send> Devres<T> { · 113 unmodified lines
304 /// pci, //304 /// pci, //
305 /// };305 /// };
306 ///306 ///
307 /// fn from_core(dev: &pci::Device<Core>, devres: Devres<pci::Bar<0x4>>) -> Result {307 /// fn from_core(dev: &pci::Device<Core<'_>>, devres: Devres<pci::Bar<'_, 0x4>>) -> Result {
308 /// let bar = devres.access(dev.as_ref())?;308 /// let bar = devres.access(dev.as_ref())?;
309 ///309 ///
310 /// let _ = bar.read32(0x0);310 /// let _ = bar.read32(0x0);
@@ -349,7 +349,7 @@ unsafe impl<T: Send> Send for Devres<T> {} · 38 unmodified lines
349// SAFETY: `Devres` can be shared with any task, if `T: Sync`.349// SAFETY: `Devres` can be shared with any task, if `T: Sync`.
350unsafe impl<T: Send + Sync> Sync for Devres<T> {}350unsafe impl<T: Send + Sync> Sync for Devres<T> {}
351 351
352impl<T: Send> Drop for Devres<T> {352impl<T: Send + 'static> Drop for Devres<T> {
353 fn drop(&mut self) {353 fn drop(&mut self) {
354 // SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data354 // SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data
355 // anymore, hence it is safe not to wait for the grace period to finish.355 // anymore, hence it is safe not to wait for the grace period to finish.
rust/kernel/dma.rs+1−1
@@ -47,7 +47,7 @@ pub type DmaAddress = bindings::dma_addr_t; · 46 unmodified lines
47/// where the underlying bus is DMA capable, such as:47/// where the underlying bus is DMA capable, such as:
48#[cfg_attr(CONFIG_PCI, doc = "* [`pci::Device`](kernel::pci::Device)")]48#[cfg_attr(CONFIG_PCI, doc = "* [`pci::Device`](kernel::pci::Device)")]
49/// * [`platform::Device`](::kernel::platform::Device)49/// * [`platform::Device`](::kernel::platform::Device)
50pub trait Device: AsRef<device::Device<Core>> {50pub trait Device<'a>: AsRef<device::Device<Core<'a>>> {
51 /// Set up the device's DMA streaming addressing capabilities.51 /// Set up the device's DMA streaming addressing capabilities.
52 ///52 ///
53 /// This method is usually called once from `probe()` as soon as the device capabilities are53 /// This method is usually called once from `probe()` as soon as the device capabilities are
rust/kernel/driver.rs+88−27
@@ -13,10 +13,13 @@ · 12 unmodified lines
13//! The main driver interface is defined by a bus specific driver trait. For instance:13//! The main driver interface is defined by a bus specific driver trait. For instance:
14//!14//!
15//! ```ignore15//! ```ignore
16//! pub trait Driver: Send {16//! pub trait Driver {
17//! /// The type holding information about each device ID supported by the driver.17//! /// The type holding information about each device ID supported by the driver.
18//! type IdInfo: 'static;18//! type IdInfo: 'static;
19//!19//!
20//! /// The type of the driver's bus device private data.
21//! type Data<'bound>: Send + 'bound;
22//!
20//! /// The table of OF device ids supported by the driver.23//! /// The table of OF device ids supported by the driver.
21//! const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;24//! const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
22//!25//!
@@ -24,10 +27,16 @@ · 1 unmodified line
24//! const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None;27//! const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None;
25//!28//!
26//! /// Driver probe.29//! /// Driver probe.
27//! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>;30//! fn probe<'bound>(
31//! dev: &'bound Device<device::Core<'_>>,
32//! id_info: &'bound Self::IdInfo,
33//! ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
28//!34//!
29//! /// Driver unbind (optional).35//! /// Driver unbind (optional).
30//! fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) {36//! fn unbind<'bound>(
37//! dev: &'bound Device<device::Core<'_>>,
38//! this: Pin<&Self::Data<'bound>>,
39//! ) {
31//! let _ = (dev, this);40//! let _ = (dev, this);
32//! }41//! }
33//! }42//! }
@@ -42,8 +51,9 @@ · 8 unmodified lines
42)]51)]
43#![cfg_attr(CONFIG_PCI, doc = "* [`pci::Driver`](kernel::pci::Driver)")]52#![cfg_attr(CONFIG_PCI, doc = "* [`pci::Driver`](kernel::pci::Driver)")]
44//!53//!
45//! The `probe()` callback should return a `impl PinInit<Self, Error>`, i.e. the driver's private54//! The `probe()` callback should return a
46//! data. The bus abstraction should store the pointer in the corresponding bus device. The generic55//! `impl PinInit<Self::Data<'bound>, Error>`, i.e. the driver's private data. The bus
56//! abstraction should store the pointer in the corresponding bus device. The generic
47//! [`Device`] infrastructure provides common helpers for this purpose on its57//! [`Device`] infrastructure provides common helpers for this purpose on its
48//! [`Device<CoreInternal>`] implementation.58//! [`Device<CoreInternal>`] implementation.
49//!59//!
@@ -118,8 +128,8 @@ pub unsafe trait DriverLayout { · 68 unmodified lines
118 /// The specific driver type embedding a `struct device_driver`.128 /// The specific driver type embedding a `struct device_driver`.
119 type DriverType: Default;129 type DriverType: Default;
120 130
121 /// The type of the driver's device private data.131 /// The type of the driver's bus device private data.
122 type DriverData;132 type DriverData<'bound>;
123 133
124 /// Byte offset of the embedded `struct device_driver` within `DriverType`.134 /// Byte offset of the embedded `struct device_driver` within `DriverType`.
125 ///135 ///
@@ -181,20 +191,20 @@ unsafe impl<T: RegistrationOps> Sync for Registration<T> {} · 55 unmodified lines
181// any thread, so `Registration` is `Send`.191// any thread, so `Registration` is `Send`.
182unsafe impl<T: RegistrationOps> Send for Registration<T> {}192unsafe impl<T: RegistrationOps> Send for Registration<T> {}
183 193
184impl<T: RegistrationOps + 'static> Registration<T> {194impl<T: RegistrationOps> Registration<T> {
185 extern "C" fn post_unbind_callback(dev: *mut bindings::device) {195 extern "C" fn post_unbind_callback(dev: *mut bindings::device) {
186 // SAFETY: The driver core only ever calls the post unbind callback with a valid pointer to196 // SAFETY: The driver core only ever calls the post unbind callback with a valid pointer to
187 // a `struct device`.197 // a `struct device`.
188 //198 //
189 // INVARIANT: `dev` is valid for the duration of the `post_unbind_callback()`.199 // INVARIANT: `dev` is valid for the duration of the `post_unbind_callback()`.
190 let dev = unsafe { &*dev.cast::<device::Device<device::CoreInternal>>() };200 let dev = unsafe { &*dev.cast::<device::Device<device::CoreInternal<'_>>>() };
191 201
192 // `remove()` and all devres callbacks have been completed at this point, hence drop the202 // `remove()` has been completed at this point; devres resources are still valid and will
193 // driver's device private data.203 // be released after the driver's bus device private data is dropped.
194 //204 //
195 // SAFETY: By the safety requirements of the `Driver` trait, `T::DriverData` is the205 // SAFETY: By the safety requirements of the `Driver` trait, `T::DriverData` is the
196 // driver's device private data type.206 // driver's bus device private data type.
197 drop(unsafe { dev.drvdata_obtain::<T::DriverData>() });207 drop(unsafe { dev.drvdata_obtain::<T::DriverData<'_>>() });
198 }208 }
199 209
200 /// Attach generic `struct device_driver` callbacks.210 /// Attach generic `struct device_driver` callbacks.
@@ -215,7 +225,10 @@ impl<T: RegistrationOps + 'static> Registration<T> { · 14 unmodified lines
215 }225 }
216 226
217 /// Creates a new instance of the registration object.227 /// Creates a new instance of the registration object.
218 pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> {228 pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error>
229 where
230 T: 'static,
231 {
219 try_pin_init!(Self {232 try_pin_init!(Self {
220 reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| {233 reg <- Opaque::try_ffi_init(|ptr: *mut T::DriverType| {
221 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.234 // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
@@ -278,6 +291,26 @@ macro_rules! module_driver { · 56 unmodified lines
278 }291 }
279}292}
280 293
294// Calling the FFI function directly from the `Adapter` impl may result in it being called
295// directly from driver modules. This happens since the Rust compiler will use monomorphisation, so
296// it might happen that functions are instantiated within the calling driver module. For now, work
297// around this with `#[inline(never)]` helpers.
298//
299// TODO: Remove once a more generic solution has been implemented. For instance, we may be able to
300// leverage `bindgen` to take care of this depending on whether a symbol is (already) exported.
301#[inline(never)]
302#[allow(clippy::missing_safety_doc)]
303#[allow(dead_code)]
304#[must_use]
305unsafe fn acpi_of_match_device(
306 adev: *const bindings::acpi_device,
307 of_match_table: *const bindings::of_device_id,
308 of_id: *mut *const bindings::of_device_id,
309) -> bool {
310 // SAFETY: Safety requirements are the same as `bindings::acpi_of_match_device`.
311 unsafe { bindings::acpi_of_match_device(adev, of_match_table, of_id) }
312}
313
281/// The bus independent adapter to match a drivers and a devices.314/// The bus independent adapter to match a drivers and a devices.
282///315///
283/// This trait should be implemented by the bus specific adapter, which represents the connection316/// This trait should be implemented by the bus specific adapter, which represents the connection
@@ -329,35 +362,63 @@ pub trait Adapter { · 45 unmodified lines
329 ///362 ///
330 /// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`].363 /// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`].
331 fn of_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {364 fn of_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> {
332 #[cfg(not(CONFIG_OF))]365 let table = Self::of_id_table()?;
366
367 #[cfg(not(any(CONFIG_OF, CONFIG_ACPI)))]
333 {368 {
334 let _ = dev;369 let _ = (dev, table);
335 None
336 }370 }
337 371
338 #[cfg(CONFIG_OF)]372 #[cfg(CONFIG_OF)]
339 {373 {
340 let table = Self::of_id_table()?;
341
342 // SAFETY:374 // SAFETY:
343 // - `table` has static lifetime, hence it's valid for read,375 // - `table` has static lifetime, hence it's valid for read,
344 // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.376 // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`.
345 let raw_id = unsafe { bindings::of_match_device(table.as_ptr(), dev.as_raw()) };377 let raw_id = unsafe { bindings::of_match_device(table.as_ptr(), dev.as_raw()) };
346 378
347 if raw_id.is_null() {379 if !raw_id.is_null() {
348 None
349 } else {
350 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`380 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`
351 // and does not add additional invariants, so it's safe to transmute.381 // and does not add additional invariants, so it's safe to transmute.
352 let id = unsafe { &*raw_id.cast::<of::DeviceId>() };382 let id = unsafe { &*raw_id.cast::<of::DeviceId>() };
353 383
354 Some(384 return Some(table.info(
355 table.info(<of::DeviceId as crate::device_id::RawDeviceIdIndex>::index(385 <of::DeviceId as crate::device_id::RawDeviceIdIndex>::index(id),
356 id,386 ));
357 )),387 }
358 )388 }
389
390 #[cfg(CONFIG_ACPI)]
391 {
392 use core::ptr;
393 use device::property::FwNode;
394
395 let mut raw_id = ptr::null();
396
397 let fwnode = dev.fwnode().map_or(ptr::null_mut(), FwNode::as_raw);
398
399 // SAFETY: `fwnode` is a pointer to a valid `fwnode_handle`. A null pointer will be
400 // passed through the function.
401 let adev = unsafe { bindings::to_acpi_device_node(fwnode) };
402
403 // SAFETY:
404 // - `adev` is a valid pointer to `acpi_device` or is null. It is guaranteed to be
405 // valid as long as `dev` is alive.
406 // - `table` has static lifetime, hence it's valid for read.
407 if unsafe { acpi_of_match_device(adev, table.as_ptr(), &raw mut raw_id) } {
408 // SAFETY:
409 // - the function returns true, therefore `raw_id` has been set to a pointer to a
410 // valid `of_device_id`.
411 // - `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id`
412 // and does not add additional invariants, so it's safe to transmute.
413 let id = unsafe { &*raw_id.cast::<of::DeviceId>() };
414
415 return Some(table.info(
416 <of::DeviceId as crate::device_id::RawDeviceIdIndex>::index(id),
417 ));
359 }418 }
360 }419 }
420
421 None
361 }422 }
362 423
363 /// Returns the driver's private data from the matching entry of any of the ID tables, if any.424 /// Returns the driver's private data from the matching entry of any of the ID tables, if any.
rust/kernel/i2c.rs+34−27
@@ -93,18 +93,18 @@ pub struct Adapter<T: Driver>(T); · 92 unmodified lines
93 93
94// SAFETY:94// SAFETY:
95// - `bindings::i2c_driver` is a C type declared as `repr(C)`.95// - `bindings::i2c_driver` is a C type declared as `repr(C)`.
96// - `T` is the type of the driver's device private data.96// - `T::Data` is the type of the driver's device private data.
97// - `struct i2c_driver` embeds a `struct device_driver`.97// - `struct i2c_driver` embeds a `struct device_driver`.
98// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.98// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
99unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {99unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> {
100 type DriverType = bindings::i2c_driver;100 type DriverType = bindings::i2c_driver;
101 type DriverData = T;101 type DriverData<'bound> = T::Data<'bound>;
102 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);102 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
103}103}
104 104
105// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if105// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
106// a preceding call to `register` has been successful.106// a preceding call to `register` has been successful.
107unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {107unsafe impl<T: Driver> driver::RegistrationOps for Adapter<T> {
108 unsafe fn register(108 unsafe fn register(
109 idrv: &Opaque<Self::DriverType>,109 idrv: &Opaque<Self::DriverType>,
110 name: &'static CStr,110 name: &'static CStr,
@@ -151,13 +151,13 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { · 40 unmodified lines
151 }151 }
152}152}
153 153
154impl<T: Driver + 'static> Adapter<T> {154impl<T: Driver> Adapter<T> {
155 extern "C" fn probe_callback(idev: *mut bindings::i2c_client) -> kernel::ffi::c_int {155 extern "C" fn probe_callback(idev: *mut bindings::i2c_client) -> kernel::ffi::c_int {
156 // SAFETY: The I2C bus only ever calls the probe callback with a valid pointer to a156 // SAFETY: The I2C bus only ever calls the probe callback with a valid pointer to a
157 // `struct i2c_client`.157 // `struct i2c_client`.
158 //158 //
159 // INVARIANT: `idev` is valid for the duration of `probe_callback()`.159 // INVARIANT: `idev` is valid for the duration of `probe_callback()`.
160 let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal>>() };160 let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal<'_>>>() };
161 161
162 let info =162 let info =
163 Self::i2c_id_info(idev).or_else(|| <Self as driver::Adapter>::id_info(idev.as_ref()));163 Self::i2c_id_info(idev).or_else(|| <Self as driver::Adapter>::id_info(idev.as_ref()));
@@ -172,24 +172,24 @@ impl<T: Driver + 'static> Adapter<T> { · 8 unmodified lines
172 172
173 extern "C" fn remove_callback(idev: *mut bindings::i2c_client) {173 extern "C" fn remove_callback(idev: *mut bindings::i2c_client) {
174 // SAFETY: `idev` is a valid pointer to a `struct i2c_client`.174 // SAFETY: `idev` is a valid pointer to a `struct i2c_client`.
175 let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal>>() };175 let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal<'_>>>() };
176 176
177 // SAFETY: `remove_callback` is only ever called after a successful call to177 // SAFETY: `remove_callback` is only ever called after a successful call to
178 // `probe_callback`, hence it's guaranteed that `I2cClient::set_drvdata()` has been called178 // `probe_callback`, hence it's guaranteed that `I2cClient::set_drvdata()` has been called
179 // and stored a `Pin<KBox<T>>`.179 // and stored a `Pin<KBox<T::Data<'_>>>`.
180 let data = unsafe { idev.as_ref().drvdata_borrow::<T>() };180 let data = unsafe { idev.as_ref().drvdata_borrow::<T::Data<'_>>() };
181 181
182 T::unbind(idev, data);182 T::unbind(idev, data);
183 }183 }
184 184
185 extern "C" fn shutdown_callback(idev: *mut bindings::i2c_client) {185 extern "C" fn shutdown_callback(idev: *mut bindings::i2c_client) {
186 // SAFETY: `shutdown_callback` is only ever called for a valid `idev`186 // SAFETY: `shutdown_callback` is only ever called for a valid `idev`
187 let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal>>() };187 let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal<'_>>>() };
188 188
189 // SAFETY: `shutdown_callback` is only ever called after a successful call to189 // SAFETY: `shutdown_callback` is only ever called after a successful call to
190 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called190 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
191 // and stored a `Pin<KBox<T>>`.191 // and stored a `Pin<KBox<T::Data<'_>>>`.
192 let data = unsafe { idev.as_ref().drvdata_borrow::<T>() };192 let data = unsafe { idev.as_ref().drvdata_borrow::<T::Data<'_>>() };
193 193
194 T::shutdown(idev, data);194 T::shutdown(idev, data);
195 }195 }
@@ -222,7 +222,7 @@ impl<T: Driver + 'static> Adapter<T> { · 26 unmodified lines
222 }222 }
223}223}
224 224
225impl<T: Driver + 'static> driver::Adapter for Adapter<T> {225impl<T: Driver> driver::Adapter for Adapter<T> {
226 type IdInfo = T::IdInfo;226 type IdInfo = T::IdInfo;
227 227
228 fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> {228 fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> {
@@ -294,22 +294,26 @@ macro_rules! module_i2c_driver { · 65 unmodified lines
294///294///
295/// impl i2c::Driver for MyDriver {295/// impl i2c::Driver for MyDriver {
296/// type IdInfo = ();296/// type IdInfo = ();
297/// type Data<'bound> = Self;
297/// const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE);298/// const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE);
298/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);299/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
299/// const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);300/// const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
300///301///
301/// fn probe(302/// fn probe<'bound>(
302/// _idev: &i2c::I2cClient<Core>,303/// _idev: &'bound i2c::I2cClient<Core<'_>>,
303/// _id_info: Option<&Self::IdInfo>,304/// _id_info: Option<&'bound Self::IdInfo>,
304/// ) -> impl PinInit<Self, Error> {305/// ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
305/// Err(ENODEV)306/// Err(ENODEV)
306/// }307/// }
307///308///
308/// fn shutdown(_idev: &i2c::I2cClient<Core>, this: Pin<&Self>) {309/// fn shutdown<'bound>(
310/// _idev: &'bound i2c::I2cClient<Core<'_>>,
311/// this: Pin<&Self::Data<'bound>>,
312/// ) {
309/// }313/// }
310/// }314/// }
311///```315///```
312pub trait Driver: Send {316pub trait Driver {
313 /// The type holding information about each device id supported by the driver.317 /// The type holding information about each device id supported by the driver.
314 // TODO: Use `associated_type_defaults` once stabilized:318 // TODO: Use `associated_type_defaults` once stabilized:
315 //319 //
@@ -318,6 +322,9 @@ pub trait Driver: Send { · 2 unmodified lines
318 // ```322 // ```
319 type IdInfo: 'static;323 type IdInfo: 'static;
320 324
325 /// The type of the driver's bus device private data.
326 type Data<'bound>: Send + 'bound;
327
321 /// The table of device ids supported by the driver.328 /// The table of device ids supported by the driver.
322 const I2C_ID_TABLE: Option<IdTable<Self::IdInfo>> = None;329 const I2C_ID_TABLE: Option<IdTable<Self::IdInfo>> = None;
323 330
@@ -331,10 +338,10 @@ pub trait Driver: Send { · 7 unmodified lines
331 ///338 ///
332 /// Called when a new i2c client is added or discovered.339 /// Called when a new i2c client is added or discovered.
333 /// Implementers should attempt to initialize the client here.340 /// Implementers should attempt to initialize the client here.
334 fn probe(341 fn probe<'bound>(
335 dev: &I2cClient<device::Core>,342 dev: &'bound I2cClient<device::Core<'_>>,
336 id_info: Option<&Self::IdInfo>,343 id_info: Option<&'bound Self::IdInfo>,
337 ) -> impl PinInit<Self, Error>;344 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
338 345
339 /// I2C driver shutdown.346 /// I2C driver shutdown.
340 ///347 ///
@@ -346,8 +353,8 @@ pub trait Driver: Send { · 5 unmodified lines
346 ///353 ///
347 /// This callback is distinct from final resource cleanup, as the driver instance remains valid354 /// This callback is distinct from final resource cleanup, as the driver instance remains valid
348 /// after it returns. Any deallocation or teardown of driver-owned resources should instead be355 /// after it returns. Any deallocation or teardown of driver-owned resources should instead be
349 /// handled in `Self::drop`.356 /// handled in `Drop`.
350 fn shutdown(dev: &I2cClient<device::Core>, this: Pin<&Self>) {357 fn shutdown<'bound>(dev: &'bound I2cClient<device::Core<'_>>, this: Pin<&Self::Data<'bound>>) {
351 let _ = (dev, this);358 let _ = (dev, this);
352 }359 }
353 360
@@ -360,8 +367,8 @@ pub trait Driver: Send { · 6 unmodified lines
360 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O367 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O
361 /// operations to gracefully tear down the device.368 /// operations to gracefully tear down the device.
362 ///369 ///
363 /// Otherwise, release operations for driver resources should be performed in `Self::drop`.370 /// Otherwise, release operations for driver resources should be performed in `Drop`.
364 fn unbind(dev: &I2cClient<device::Core>, this: Pin<&Self>) {371 fn unbind<'bound>(dev: &'bound I2cClient<device::Core<'_>>, this: Pin<&Self::Data<'bound>>) {
365 let _ = (dev, this);372 let _ = (dev, this);
366 }373 }
367}374}
rust/kernel/io/mem.rs+62−59
@@ -62,33 +62,31 @@ impl<'a> IoRequest<'a> { · 61 unmodified lines
62 ///62 ///
63 /// impl platform::Driver for SampleDriver {63 /// impl platform::Driver for SampleDriver {
64 /// # type IdInfo = ();64 /// # type IdInfo = ();
65 /// # type Data<'bound> = Self;
65 ///66 ///
66 /// fn probe(67 /// fn probe<'bound>(
67 /// pdev: &platform::Device<Core>,68 /// pdev: &'bound platform::Device<Core<'_>>,
68 /// info: Option<&Self::IdInfo>,69 /// info: Option<&'bound Self::IdInfo>,
69 /// ) -> impl PinInit<Self, Error> {70 /// ) -> impl PinInit<Self, Error> + 'bound {
70 /// let offset = 0; // Some offset.71 /// let offset = 0; // Some offset.
71 ///72 ///
72 /// // If the size is known at compile time, use [`Self::iomap_sized`].73 /// // If the size is known at compile time, use [`Self::iomap_sized`].
73 /// //74 /// //
74 /// // No runtime checks will apply when reading and writing.75 /// // No runtime checks will apply when reading and writing.
75 /// let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;76 /// let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
76 /// let iomem = request.iomap_sized::<42>();77 /// let iomem = request.iomap_sized::<42>()?;
77 /// let iomem = KBox::pin_init(iomem, GFP_KERNEL)?;
78 ///
79 /// let io = iomem.access(pdev.as_ref())?;
80 ///78 ///
81 /// // Read and write a 32-bit value at `offset`.79 /// // Read and write a 32-bit value at `offset`.
82 /// let data = io.read32(offset);80 /// let data = iomem.read32(offset);
83 ///81 ///
84 /// io.write32(data, offset);82 /// iomem.write32(data, offset);
85 ///83 ///
86 /// # Ok(SampleDriver)84 /// # Ok(SampleDriver)
87 /// }85 /// }
88 /// }86 /// }
89 /// ```87 /// ```
90 pub fn iomap_sized<const SIZE: usize>(self) -> impl PinInit<Devres<IoMem<SIZE>>, Error> + 'a {88 pub fn iomap_sized<const SIZE: usize>(self) -> Result<IoMem<'a, SIZE>> {
91 IoMem::new(self)89 IoMem::ioremap(self.device, self.resource)
92 }90 }
93 91
94 /// Same as [`Self::iomap_sized`] but with exclusive access to the92 /// Same as [`Self::iomap_sized`] but with exclusive access to the
@@ -97,10 +95,8 @@ impl<'a> IoRequest<'a> { · 2 unmodified lines
97 /// This uses the [`ioremap()`] C API.95 /// This uses the [`ioremap()`] C API.
98 ///96 ///
99 /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device97 /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device
100 pub fn iomap_exclusive_sized<const SIZE: usize>(98 pub fn iomap_exclusive_sized<const SIZE: usize>(self) -> Result<ExclusiveIoMem<'a, SIZE>> {
101 self,99 ExclusiveIoMem::ioremap(self.device, self.resource)
102 ) -> impl PinInit<Devres<ExclusiveIoMem<SIZE>>, Error> + 'a {
103 ExclusiveIoMem::new(self)
104 }100 }
105 101
106 /// Maps an [`IoRequest`] where the size is not known at compile time,102 /// Maps an [`IoRequest`] where the size is not known at compile time,
@@ -126,11 +122,12 @@ impl<'a> IoRequest<'a> { · 19 unmodified lines
126 ///122 ///
127 /// impl platform::Driver for SampleDriver {123 /// impl platform::Driver for SampleDriver {
128 /// # type IdInfo = ();124 /// # type IdInfo = ();
125 /// # type Data<'bound> = Self;
129 ///126 ///
130 /// fn probe(127 /// fn probe<'bound>(
131 /// pdev: &platform::Device<Core>,128 /// pdev: &'bound platform::Device<Core<'_>>,
132 /// info: Option<&Self::IdInfo>,129 /// info: Option<&'bound Self::IdInfo>,
133 /// ) -> impl PinInit<Self, Error> {130 /// ) -> impl PinInit<Self, Error> + 'bound {
134 /// let offset = 0; // Some offset.131 /// let offset = 0; // Some offset.
135 ///132 ///
136 /// // Unlike [`Self::iomap_sized`], here the size of the memory region133 /// // Unlike [`Self::iomap_sized`], here the size of the memory region
@@ -138,27 +135,24 @@ impl<'a> IoRequest<'a> { · 1 unmodified line
138 /// // family of functions should be used, leading to runtime checks on every135 /// // family of functions should be used, leading to runtime checks on every
139 /// // access.136 /// // access.
140 /// let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;137 /// let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
141 /// let iomem = request.iomap();138 /// let iomem = request.iomap()?;
142 /// let iomem = KBox::pin_init(iomem, GFP_KERNEL)?;
143 ///
144 /// let io = iomem.access(pdev.as_ref())?;
145 ///139 ///
146 /// let data = io.try_read32(offset)?;140 /// let data = iomem.try_read32(offset)?;
147 ///141 ///
148 /// io.try_write32(data, offset)?;142 /// iomem.try_write32(data, offset)?;
149 ///143 ///
150 /// # Ok(SampleDriver)144 /// # Ok(SampleDriver)
151 /// }145 /// }
152 /// }146 /// }
153 /// ```147 /// ```
154 pub fn iomap(self) -> impl PinInit<Devres<IoMem<0>>, Error> + 'a {148 pub fn iomap(self) -> Result<IoMem<'a>> {
155 Self::iomap_sized::<0>(self)149 self.iomap_sized::<0>()
156 }150 }
157 151
158 /// Same as [`Self::iomap`] but with exclusive access to the underlying152 /// Same as [`Self::iomap`] but with exclusive access to the underlying
159 /// region.153 /// region.
160 pub fn iomap_exclusive(self) -> impl PinInit<Devres<ExclusiveIoMem<0>>, Error> + 'a {154 pub fn iomap_exclusive(self) -> Result<ExclusiveIoMem<'a, 0>> {
161 Self::iomap_exclusive_sized::<0>(self)155 self.iomap_exclusive_sized::<0>()
162 }156 }
163}157}
164 158
@@ -167,9 +161,9 @@ impl<'a> IoRequest<'a> { · 2 unmodified lines
167/// # Invariants161/// # Invariants
168///162///
169/// - [`ExclusiveIoMem`] has exclusive access to the underlying [`IoMem`].163/// - [`ExclusiveIoMem`] has exclusive access to the underlying [`IoMem`].
170pub struct ExclusiveIoMem<const SIZE: usize> {164pub struct ExclusiveIoMem<'a, const SIZE: usize> {
171 /// The underlying `IoMem` instance.165 /// The underlying `IoMem` instance.
172 iomem: IoMem<SIZE>,166 iomem: IoMem<'a, SIZE>,
173 167
174 /// The region abstraction. This represents exclusive access to the168 /// The region abstraction. This represents exclusive access to the
175 /// range represented by the underlying `iomem`.169 /// range represented by the underlying `iomem`.
@@ -178,9 +172,9 @@ pub struct ExclusiveIoMem<const SIZE: usize> { · 2 unmodified lines
178 _region: Region,172 _region: Region,
179}173}
180 174
181impl<const SIZE: usize> ExclusiveIoMem<SIZE> {175impl<'a, const SIZE: usize> ExclusiveIoMem<'a, SIZE> {
182 /// Creates a new `ExclusiveIoMem` instance.176 /// Creates a new `ExclusiveIoMem` instance.
183 fn ioremap(resource: &Resource) -> Result<Self> {177 fn ioremap(dev: &'a Device<Bound>, resource: &Resource) -> Result<Self> {
184 let start = resource.start();178 let start = resource.start();
185 let size = resource.size();179 let size = resource.size();
186 let name = resource.name().unwrap_or_default();180 let name = resource.name().unwrap_or_default();
@@ -194,26 +188,29 @@ impl<const SIZE: usize> ExclusiveIoMem<SIZE> { · 7 unmodified lines
194 )188 )
195 .ok_or(EBUSY)?;189 .ok_or(EBUSY)?;
196 190
197 let iomem = IoMem::ioremap(resource)?;191 let iomem = IoMem::ioremap(dev, resource)?;
198 192
199 let iomem = ExclusiveIoMem {193 Ok(ExclusiveIoMem {
200 iomem,194 iomem,
201 _region: region,195 _region: region,
202 };196 })
203
204 Ok(iomem)
205 }197 }
206 198
207 /// Creates a new `ExclusiveIoMem` instance from a previously acquired [`IoRequest`].199 /// Consume the `ExclusiveIoMem` and register it as a device-managed resource.
208 pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> + 'a {200 ///
209 let dev = io_request.device;201 /// The returned `Devres<ExclusiveIoMem<'static, SIZE>>` can outlive the original lifetime
210 let res = io_request.resource;202 /// `'a`. Access to the I/O memory is revoked when the device is unbound.
211 203 pub fn into_devres(self) -> Result<Devres<ExclusiveIoMem<'static, SIZE>>> {
212 Devres::new(dev, Self::ioremap(res))204 // SAFETY: Casting to `'static` is sound because `Devres` guarantees the
205 // `ExclusiveIoMem` does not actually outlive the device -- access is revoked and the
206 // resource is released when the device is unbound.
207 let iomem: ExclusiveIoMem<'static, SIZE> = unsafe { core::mem::transmute(self) };
208 let dev = iomem.iomem.dev;
209 Devres::new(dev, iomem)
213 }210 }
214}211}
215 212
216impl<const SIZE: usize> Deref for ExclusiveIoMem<SIZE> {213impl<const SIZE: usize> Deref for ExclusiveIoMem<'_, SIZE> {
217 type Target = Mmio<SIZE>;214 type Target = Mmio<SIZE>;
218 215
219 fn deref(&self) -> &Self::Target {216 fn deref(&self) -> &Self::Target {
@@ -230,12 +227,13 @@ impl<const SIZE: usize> Deref for ExclusiveIoMem<SIZE> { · 10 unmodified lines
230///227///
231/// [`IoMem`] always holds an [`MmioRaw`] instance that holds a valid pointer to the228/// [`IoMem`] always holds an [`MmioRaw`] instance that holds a valid pointer to the
232/// start of the I/O memory mapped region.229/// start of the I/O memory mapped region.
233pub struct IoMem<const SIZE: usize = 0> {230pub struct IoMem<'a, const SIZE: usize = 0> {
231 dev: &'a Device<Bound>,
234 io: MmioRaw<SIZE>,232 io: MmioRaw<SIZE>,
235}233}
236 234
237impl<const SIZE: usize> IoMem<SIZE> {235impl<'a, const SIZE: usize> IoMem<'a, SIZE> {
238 fn ioremap(resource: &Resource) -> Result<Self> {236 fn ioremap(dev: &'a Device<Bound>, resource: &Resource) -> Result<Self> {
239 // Note: Some ioremap() implementations use types that depend on the CPU237 // Note: Some ioremap() implementations use types that depend on the CPU
240 // word width rather than the bus address width.238 // word width rather than the bus address width.
241 //239 //
@@ -267,28 +265,33 @@ impl<const SIZE: usize> IoMem<SIZE> { · 25 unmodified lines
267 }265 }
268 266
269 let io = MmioRaw::new(addr as usize, size)?;267 let io = MmioRaw::new(addr as usize, size)?;
270 let io = IoMem { io };
271 268
272 Ok(io)269 Ok(IoMem { dev, io })
273 }270 }
274 271
275 /// Creates a new `IoMem` instance from a previously acquired [`IoRequest`].272 /// Consume the `IoMem` and register it as a device-managed resource.
276 pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> + 'a {273 ///
277 let dev = io_request.device;274 /// The returned `Devres<IoMem<'static, SIZE>>` can outlive the original
278 let res = io_request.resource;275 /// lifetime `'a`. Access to the I/O memory is revoked when the device
279 276 /// is unbound.
280 Devres::new(dev, Self::ioremap(res))277 pub fn into_devres(self) -> Result<Devres<IoMem<'static, SIZE>>> {
278 // SAFETY: Casting to `'static` is sound because `Devres` guarantees the `IoMem` does not
279 // actually outlive the device -- access is revoked and the resource is released when the
280 // device is unbound.
281 let iomem: IoMem<'static, SIZE> = unsafe { core::mem::transmute(self) };
282 let dev = iomem.dev;
283 Devres::new(dev, iomem)
281 }284 }
282}285}
283 286
284impl<const SIZE: usize> Drop for IoMem<SIZE> {287impl<const SIZE: usize> Drop for IoMem<'_, SIZE> {
285 fn drop(&mut self) {288 fn drop(&mut self) {
286 // SAFETY: Safe as by the invariant of `Io`.289 // SAFETY: Safe as by the invariant of `Io`.
287 unsafe { bindings::iounmap(self.io.addr() as *mut c_void) }290 unsafe { bindings::iounmap(self.io.addr() as *mut c_void) }
288 }291 }
289}292}
290 293
291impl<const SIZE: usize> Deref for IoMem<SIZE> {294impl<const SIZE: usize> Deref for IoMem<'_, SIZE> {
292 type Target = Mmio<SIZE>;295 type Target = Mmio<SIZE>;
293 296
294 fn deref(&self) -> &Self::Target {297 fn deref(&self) -> &Self::Target {
rust/kernel/pci.rs+31−20
@@ -59,18 +59,18 @@ pub struct Adapter<T: Driver>(T); · 58 unmodified lines
59 59
60// SAFETY:60// SAFETY:
61// - `bindings::pci_driver` is a C type declared as `repr(C)`.61// - `bindings::pci_driver` is a C type declared as `repr(C)`.
62// - `T` is the type of the driver's device private data.62// - `T::Data` is the type of the driver's device private data.
63// - `struct pci_driver` embeds a `struct device_driver`.63// - `struct pci_driver` embeds a `struct device_driver`.
64// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.64// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
65unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {65unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> {
66 type DriverType = bindings::pci_driver;66 type DriverType = bindings::pci_driver;
67 type DriverData = T;67 type DriverData<'bound> = T::Data<'bound>;
68 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);68 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
69}69}
70 70
71// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if71// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
72// a preceding call to `register` has been successful.72// a preceding call to `register` has been successful.
73unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {73unsafe impl<T: Driver> driver::RegistrationOps for Adapter<T> {
74 unsafe fn register(74 unsafe fn register(
75 pdrv: &Opaque<Self::DriverType>,75 pdrv: &Opaque<Self::DriverType>,
76 name: &'static CStr,76 name: &'static CStr,
@@ -96,7 +96,7 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { · 19 unmodified lines
96 }96 }
97}97}
98 98
99impl<T: Driver + 'static> Adapter<T> {99impl<T: Driver> Adapter<T> {
100 extern "C" fn probe_callback(100 extern "C" fn probe_callback(
101 pdev: *mut bindings::pci_dev,101 pdev: *mut bindings::pci_dev,
102 id: *const bindings::pci_device_id,102 id: *const bindings::pci_device_id,
@@ -105,7 +105,7 @@ impl<T: Driver + 'static> Adapter<T> { · 2 unmodified lines
105 // `struct pci_dev`.105 // `struct pci_dev`.
106 //106 //
107 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`.107 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`.
108 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() };108 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal<'_>>>() };
109 109
110 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct pci_device_id` and110 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct pci_device_id` and
111 // does not add additional invariants, so it's safe to transmute.111 // does not add additional invariants, so it's safe to transmute.
@@ -125,12 +125,12 @@ impl<T: Driver + 'static> Adapter<T> { · 13 unmodified lines
125 // `struct pci_dev`.125 // `struct pci_dev`.
126 //126 //
127 // INVARIANT: `pdev` is valid for the duration of `remove_callback()`.127 // INVARIANT: `pdev` is valid for the duration of `remove_callback()`.
128 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() };128 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal<'_>>>() };
129 129
130 // SAFETY: `remove_callback` is only ever called after a successful call to130 // SAFETY: `remove_callback` is only ever called after a successful call to
131 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called131 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
132 // and stored a `Pin<KBox<T>>`.132 // and stored a `Pin<KBox<T::Data<'_>>>`.
133 let data = unsafe { pdev.as_ref().drvdata_borrow::<T>() };133 let data = unsafe { pdev.as_ref().drvdata_borrow::<T::Data<'_>>() };
134 134
135 T::unbind(pdev, data);135 T::unbind(pdev, data);
136 }136 }
@@ -279,19 +279,20 @@ macro_rules! pci_device_table { · 142 unmodified lines
279///279///
280/// impl pci::Driver for MyDriver {280/// impl pci::Driver for MyDriver {
281/// type IdInfo = ();281/// type IdInfo = ();
282/// type Data<'bound> = Self;
282/// const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;283/// const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
283///284///
284/// fn probe(285/// fn probe<'bound>(
285/// _pdev: &pci::Device<Core>,286/// _pdev: &'bound pci::Device<Core<'_>>,
286/// _id_info: &Self::IdInfo,287/// _id_info: &'bound Self::IdInfo,
287/// ) -> impl PinInit<Self, Error> {288/// ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
288/// Err(ENODEV)289/// Err(ENODEV)
289/// }290/// }
290/// }291/// }
291///```292///```
292/// Drivers must implement this trait in order to get a PCI driver registered. Please refer to the293/// Drivers must implement this trait in order to get a PCI driver registered. Please refer to the
293/// `Adapter` documentation for an example.294/// `Adapter` documentation for an example.
294pub trait Driver: Send {295pub trait Driver {
295 /// The type holding information about each device id supported by the driver.296 /// The type holding information about each device id supported by the driver.
296 // TODO: Use `associated_type_defaults` once stabilized:297 // TODO: Use `associated_type_defaults` once stabilized:
297 //298 //
@@ -300,6 +301,9 @@ pub trait Driver: Send { · 2 unmodified lines
300 // ```301 // ```
301 type IdInfo: 'static;302 type IdInfo: 'static;
302 303
304 /// The type of the driver's bus device private data.
305 type Data<'bound>: Send + 'bound;
306
303 /// The table of device ids supported by the driver.307 /// The table of device ids supported by the driver.
304 const ID_TABLE: IdTable<Self::IdInfo>;308 const ID_TABLE: IdTable<Self::IdInfo>;
305 309
@@ -307,7 +311,10 @@ pub trait Driver: Send { · 1 unmodified line
307 ///311 ///
308 /// Called when a new pci device is added or discovered. Implementers should312 /// Called when a new pci device is added or discovered. Implementers should
309 /// attempt to initialize the device here.313 /// attempt to initialize the device here.
310 fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>;314 fn probe<'bound>(
315 dev: &'bound Device<device::Core<'_>>,
316 id_info: &'bound Self::IdInfo,
317 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
311 318
312 /// PCI driver unbind.319 /// PCI driver unbind.
313 ///320 ///
@@ -318,8 +325,8 @@ pub trait Driver: Send { · 4 unmodified lines
318 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O325 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O
319 /// operations to gracefully tear down the device.326 /// operations to gracefully tear down the device.
320 ///327 ///
321 /// Otherwise, release operations for driver resources should be performed in `Self::drop`.328 /// Otherwise, release operations for driver resources should be performed in `Drop`.
322 fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) {329 fn unbind<'bound>(dev: &'bound Device<device::Core<'_>>, this: Pin<&Self::Data<'bound>>) {
323 let _ = (dev, this);330 let _ = (dev, this);
324 }331 }
325}332}
@@ -354,7 +361,7 @@ impl Device { · 28 unmodified lines
354 ///361 ///
355 /// ```362 /// ```
356 /// # use kernel::{device::Core, pci::{self, Vendor}, prelude::*};363 /// # use kernel::{device::Core, pci::{self, Vendor}, prelude::*};
357 /// fn log_device_info(pdev: &pci::Device<Core>) -> Result {364 /// fn log_device_info(pdev: &pci::Device<Core<'_>>) -> Result {
358 /// // Get an instance of `Vendor`.365 /// // Get an instance of `Vendor`.
359 /// let vendor = pdev.vendor_id();366 /// let vendor = pdev.vendor_id();
360 /// dev_info!(367 /// dev_info!(
@@ -445,7 +452,7 @@ impl Device { · 84 unmodified lines
445 }452 }
446}453}
447 454
448impl Device<device::Core> {455impl<'a> Device<device::Core<'a>> {
449 /// Enable memory resources for this device.456 /// Enable memory resources for this device.
450 pub fn enable_device_mem(&self) -> Result {457 pub fn enable_device_mem(&self) -> Result {
451 // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`.458 // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`.
@@ -471,7 +478,7 @@ unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx> · 19 unmodified lines
471kernel::impl_device_context_deref!(unsafe { Device });478kernel::impl_device_context_deref!(unsafe { Device });
472kernel::impl_device_context_into_aref!(Device);479kernel::impl_device_context_into_aref!(Device);
473 480
474impl crate::dma::Device for Device<device::Core> {}481impl<'a> crate::dma::Device<'a> for Device<device::Core<'a>> {}
475 482
476// SAFETY: Instances of `Device` are always reference-counted.483// SAFETY: Instances of `Device` are always reference-counted.
477unsafe impl crate::sync::aref::AlwaysRefCounted for Device {484unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
@@ -523,3 +530,7 @@ unsafe impl Send for Device {} · 45 unmodified lines
523// SAFETY: `Device` can be shared among threads because all methods of `Device`530// SAFETY: `Device` can be shared among threads because all methods of `Device`
524// (i.e. `Device<Normal>) are thread safe.531// (i.e. `Device<Normal>) are thread safe.
525unsafe impl Sync for Device {}532unsafe impl Sync for Device {}
533
534// SAFETY: Same as `Device<Normal>` -- the underlying `struct pci_dev` is the same;
535// `Bound` is a zero-sized type-state marker that does not affect thread safety.
536unsafe impl Sync for Device<device::Bound> {}
rust/kernel/pci/id.rs+1−1
@@ -19,7 +19,7 @@ use crate::{ · 18 unmodified lines
19///19///
20/// ```20/// ```
21/// # use kernel::{device::Core, pci::{self, Class}, prelude::*};21/// # use kernel::{device::Core, pci::{self, Class}, prelude::*};
22/// fn probe_device(pdev: &pci::Device<Core>) -> Result {22/// fn probe_device(pdev: &pci::Device<Core<'_>>) -> Result {
23/// let pci_class = pdev.pci_class();23/// let pci_class = pdev.pci_class();
24/// dev_info!(24/// dev_info!(
25/// pdev,25/// pdev,
rust/kernel/pci/io.rs+31−23
@@ -14,8 +14,7 @@ use crate::{ · 13 unmodified lines
14 Mmio,14 Mmio,
15 MmioRaw, //15 MmioRaw, //
16 },16 },
17 prelude::*,17 prelude::*, //
18 sync::aref::ARef, //
19};18};
20use core::{19use core::{
21 marker::PhantomData,20 marker::PhantomData,
@@ -146,14 +145,18 @@ impl<'a, S: ConfigSpaceKind> IoKnownSize for ConfigSpace<'a, S> { · 124 unmodified lines
146///145///
147/// `Bar` always holds an `IoRaw` instance that holds a valid pointer to the start of the I/O146/// `Bar` always holds an `IoRaw` instance that holds a valid pointer to the start of the I/O
148/// memory mapped PCI BAR and its size.147/// memory mapped PCI BAR and its size.
149pub struct Bar<const SIZE: usize = 0> {148pub struct Bar<'a, const SIZE: usize = 0> {
150 pdev: ARef<Device>,149 pdev: &'a Device<device::Bound>,
151 io: MmioRaw<SIZE>,150 io: MmioRaw<SIZE>,
152 num: i32,151 num: i32,
153}152}
154 153
155impl<const SIZE: usize> Bar<SIZE> {154impl<'a, const SIZE: usize> Bar<'a, SIZE> {
156 pub(super) fn new(pdev: &Device, num: u32, name: &CStr) -> Result<Self> {155 pub(super) fn new(
156 pdev: &'a Device<device::Bound>,
157 num: u32,
158 name: &'static CStr,
159 ) -> Result<Self> {
157 let len = pdev.resource_len(num)?;160 let len = pdev.resource_len(num)?;
158 if len == 0 {161 if len == 0 {
159 return Err(ENOMEM);162 return Err(ENOMEM);
@@ -196,11 +199,7 @@ impl<const SIZE: usize> Bar<SIZE> { · 36 unmodified lines
196 }199 }
197 };200 };
198 201
199 Ok(Bar {202 Ok(Bar { pdev, io, num })
200 pdev: pdev.into(),
201 io,
202 num,
203 })
204 }203 }
205 204
206 /// # Safety205 /// # Safety
@@ -219,11 +218,24 @@ impl<const SIZE: usize> Bar<SIZE> { · 12 unmodified lines
219 218
220 fn release(&self) {219 fn release(&self) {
221 // SAFETY: The safety requirements are guaranteed by the type invariant of `self.pdev`.220 // SAFETY: The safety requirements are guaranteed by the type invariant of `self.pdev`.
222 unsafe { Self::do_release(&self.pdev, self.io.addr(), self.num) };221 unsafe { Self::do_release(self.pdev, self.io.addr(), self.num) };
222 }
223
224 /// Consume the `Bar` and register it as a device-managed resource.
225 ///
226 /// The returned `Devres<Bar<'static, SIZE>>` can outlive the original lifetime `'a`. Access
227 /// to the BAR is revoked when the device is unbound.
228 pub fn into_devres(self) -> Result<Devres<Bar<'static, SIZE>>> {
229 // SAFETY: Casting to `'static` is sound because `Devres` guarantees the `Bar` does not
230 // actually outlive the device -- access is revoked and the resource is released when the
231 // device is unbound.
232 let bar: Bar<'static, SIZE> = unsafe { core::mem::transmute(self) };
233 let pdev = bar.pdev;
234 Devres::new(pdev.as_ref(), bar)
223 }235 }
224}236}
225 237
226impl Bar {238impl Bar<'_> {
227 #[inline]239 #[inline]
228 pub(super) fn index_is_valid(index: u32) -> bool {240 pub(super) fn index_is_valid(index: u32) -> bool {
229 // A `struct pci_dev` owns an array of resources with at most `PCI_NUM_RESOURCES` entries.241 // A `struct pci_dev` owns an array of resources with at most `PCI_NUM_RESOURCES` entries.
@@ -231,13 +243,13 @@ impl Bar { · 1 unmodified line
231 }243 }
232}244}
233 245
234impl<const SIZE: usize> Drop for Bar<SIZE> {246impl<const SIZE: usize> Drop for Bar<'_, SIZE> {
235 fn drop(&mut self) {247 fn drop(&mut self) {
236 self.release();248 self.release();
237 }249 }
238}250}
239 251
240impl<const SIZE: usize> Deref for Bar<SIZE> {252impl<const SIZE: usize> Deref for Bar<'_, SIZE> {
241 type Target = Mmio<SIZE>;253 type Target = Mmio<SIZE>;
242 254
243 fn deref(&self) -> &Self::Target {255 fn deref(&self) -> &Self::Target {
@@ -252,17 +264,13 @@ impl Device<device::Bound> { · 8 unmodified lines
252 pub fn iomap_region_sized<'a, const SIZE: usize>(264 pub fn iomap_region_sized<'a, const SIZE: usize>(
253 &'a self,265 &'a self,
254 bar: u32,266 bar: u32,
255 name: &'a CStr,267 name: &'static CStr,
256 ) -> impl PinInit<Devres<Bar<SIZE>>, Error> + 'a {268 ) -> Result<Bar<'a, SIZE>> {
257 Devres::new(self.as_ref(), Bar::<SIZE>::new(self, bar, name))269 Bar::new(self, bar, name)
258 }270 }
259 271
260 /// Maps an entire PCI BAR after performing a region-request on it.272 /// Maps an entire PCI BAR after performing a region-request on it.
261 pub fn iomap_region<'a>(273 pub fn iomap_region<'a>(&'a self, bar: u32, name: &'static CStr) -> Result<Bar<'a>> {
262 &'a self,
263 bar: u32,
264 name: &'a CStr,
265 ) -> impl PinInit<Devres<Bar>, Error> + 'a {
266 self.iomap_region_sized::<0>(bar, name)274 self.iomap_region_sized::<0>(bar, name)
267 }275 }
268 276
rust/kernel/platform.rs+33−23
@@ -45,18 +45,18 @@ pub struct Adapter<T: Driver>(T); · 44 unmodified lines
45 45
46// SAFETY:46// SAFETY:
47// - `bindings::platform_driver` is a C type declared as `repr(C)`.47// - `bindings::platform_driver` is a C type declared as `repr(C)`.
48// - `T` is the type of the driver's device private data.48// - `T::Data` is the type of the driver's device private data.
49// - `struct platform_driver` embeds a `struct device_driver`.49// - `struct platform_driver` embeds a `struct device_driver`.
50// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.50// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
51unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {51unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> {
52 type DriverType = bindings::platform_driver;52 type DriverType = bindings::platform_driver;
53 type DriverData = T;53 type DriverData<'bound> = T::Data<'bound>;
54 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);54 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
55}55}
56 56
57// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if57// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
58// a preceding call to `register` has been successful.58// a preceding call to `register` has been successful.
59unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {59unsafe impl<T: Driver> driver::RegistrationOps for Adapter<T> {
60 unsafe fn register(60 unsafe fn register(
61 pdrv: &Opaque<Self::DriverType>,61 pdrv: &Opaque<Self::DriverType>,
62 name: &'static CStr,62 name: &'static CStr,
@@ -82,7 +82,9 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { · 19 unmodified lines
82 }82 }
83 83
84 // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.84 // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
85 to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })85 to_result(unsafe {
86 bindings::__platform_driver_register(pdrv.get(), module.0, name.as_char_ptr())
87 })
86 }88 }
87 89
88 unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {90 unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {
@@ -91,13 +93,13 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { · 2 unmodified lines
91 }93 }
92}94}
93 95
94impl<T: Driver + 'static> Adapter<T> {96impl<T: Driver> Adapter<T> {
95 extern "C" fn probe_callback(pdev: *mut bindings::platform_device) -> kernel::ffi::c_int {97 extern "C" fn probe_callback(pdev: *mut bindings::platform_device) -> kernel::ffi::c_int {
96 // SAFETY: The platform bus only ever calls the probe callback with a valid pointer to a98 // SAFETY: The platform bus only ever calls the probe callback with a valid pointer to a
97 // `struct platform_device`.99 // `struct platform_device`.
98 //100 //
99 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`.101 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`.
100 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() };102 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal<'_>>>() };
101 let info = <Self as driver::Adapter>::id_info(pdev.as_ref());103 let info = <Self as driver::Adapter>::id_info(pdev.as_ref());
102 104
103 from_result(|| {105 from_result(|| {
@@ -113,18 +115,18 @@ impl<T: Driver + 'static> Adapter<T> { · 9 unmodified lines
113 // `struct platform_device`.115 // `struct platform_device`.
114 //116 //
115 // INVARIANT: `pdev` is valid for the duration of `remove_callback()`.117 // INVARIANT: `pdev` is valid for the duration of `remove_callback()`.
116 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() };118 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal<'_>>>() };
117 119
118 // SAFETY: `remove_callback` is only ever called after a successful call to120 // SAFETY: `remove_callback` is only ever called after a successful call to
119 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called121 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
120 // and stored a `Pin<KBox<T>>`.122 // and stored a `Pin<KBox<T::Data<'_>>>`.
121 let data = unsafe { pdev.as_ref().drvdata_borrow::<T>() };123 let data = unsafe { pdev.as_ref().drvdata_borrow::<T::Data<'_>>() };
122 124
123 T::unbind(pdev, data);125 T::unbind(pdev, data);
124 }126 }
125}127}
126 128
127impl<T: Driver + 'static> driver::Adapter for Adapter<T> {129impl<T: Driver> driver::Adapter for Adapter<T> {
128 type IdInfo = T::IdInfo;130 type IdInfo = T::IdInfo;
129 131
130 fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> {132 fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> {
@@ -192,18 +194,19 @@ macro_rules! module_platform_driver { · 61 unmodified lines
192///194///
193/// impl platform::Driver for MyDriver {195/// impl platform::Driver for MyDriver {
194/// type IdInfo = ();196/// type IdInfo = ();
197/// type Data<'bound> = Self;
195/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);198/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
196/// const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);199/// const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
197///200///
198/// fn probe(201/// fn probe<'bound>(
199/// _pdev: &platform::Device<Core>,202/// _pdev: &'bound platform::Device<Core<'_>>,
200/// _id_info: Option<&Self::IdInfo>,203/// _id_info: Option<&'bound Self::IdInfo>,
201/// ) -> impl PinInit<Self, Error> {204/// ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
202/// Err(ENODEV)205/// Err(ENODEV)
203/// }206/// }
204/// }207/// }
205///```208///```
206pub trait Driver: Send {209pub trait Driver {
207 /// The type holding driver private data about each device id supported by the driver.210 /// The type holding driver private data about each device id supported by the driver.
208 // TODO: Use associated_type_defaults once stabilized:211 // TODO: Use associated_type_defaults once stabilized:
209 //212 //
@@ -212,6 +215,9 @@ pub trait Driver: Send { · 2 unmodified lines
212 // ```215 // ```
213 type IdInfo: 'static;216 type IdInfo: 'static;
214 217
218 /// The type of the driver's bus device private data.
219 type Data<'bound>: Send + 'bound;
220
215 /// The table of OF device ids supported by the driver.221 /// The table of OF device ids supported by the driver.
216 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;222 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
217 223
@@ -222,10 +228,10 @@ pub trait Driver: Send { · 4 unmodified lines
222 ///228 ///
223 /// Called when a new platform device is added or discovered.229 /// Called when a new platform device is added or discovered.
224 /// Implementers should attempt to initialize the device here.230 /// Implementers should attempt to initialize the device here.
225 fn probe(231 fn probe<'bound>(
226 dev: &Device<device::Core>,232 dev: &'bound Device<device::Core<'_>>,
227 id_info: Option<&Self::IdInfo>,233 id_info: Option<&'bound Self::IdInfo>,
228 ) -> impl PinInit<Self, Error>;234 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
229 235
230 /// Platform driver unbind.236 /// Platform driver unbind.
231 ///237 ///
@@ -236,8 +242,8 @@ pub trait Driver: Send { · 4 unmodified lines
236 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O242 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O
237 /// operations to gracefully tear down the device.243 /// operations to gracefully tear down the device.
238 ///244 ///
239 /// Otherwise, release operations for driver resources should be performed in `Self::drop`.245 /// Otherwise, release operations for driver resources should be performed in `Drop`.
240 fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) {246 fn unbind<'bound>(dev: &'bound Device<device::Core<'_>>, this: Pin<&Self::Data<'bound>>) {
241 let _ = (dev, this);247 let _ = (dev, this);
242 }248 }
243}249}
@@ -509,7 +515,7 @@ impl Device<Bound> { · 265 unmodified lines
509kernel::impl_device_context_deref!(unsafe { Device });515kernel::impl_device_context_deref!(unsafe { Device });
510kernel::impl_device_context_into_aref!(Device);516kernel::impl_device_context_into_aref!(Device);
511 517
512impl crate::dma::Device for Device<device::Core> {}518impl<'a> crate::dma::Device<'a> for Device<device::Core<'a>> {}
513 519
514// SAFETY: Instances of `Device` are always reference-counted.520// SAFETY: Instances of `Device` are always reference-counted.
515unsafe impl crate::sync::aref::AlwaysRefCounted for Device {521unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
@@ -561,3 +567,7 @@ unsafe impl Send for Device {} · 45 unmodified lines
561// SAFETY: `Device` can be shared among threads because all methods of `Device`567// SAFETY: `Device` can be shared among threads because all methods of `Device`
562// (i.e. `Device<Normal>) are thread safe.568// (i.e. `Device<Normal>) are thread safe.
563unsafe impl Sync for Device {}569unsafe impl Sync for Device {}
570
571// SAFETY: Same as `Device<Normal>` -- the underlying `struct platform_device` is the same;
572// `Bound` is a zero-sized type-state marker that does not affect thread safety.
573unsafe impl Sync for Device<device::Bound> {}
rust/kernel/types.rs+10−2
@@ -11,6 +11,10 @@ use core::{ · 10 unmodified lines
11};11};
12use pin_init::{PinInit, Wrapper, Zeroable};12use pin_init::{PinInit, Wrapper, Zeroable};
13 13
14#[doc(hidden)]
15pub mod for_lt;
16pub use for_lt::ForLt;
17
14/// Used to transfer ownership to and from foreign (non-Rust) languages.18/// Used to transfer ownership to and from foreign (non-Rust) languages.
15///19///
16/// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and20/// Ownership is transferred from Rust to a foreign language by calling [`Self::into_foreign`] and
@@ -27,10 +31,14 @@ pub unsafe trait ForeignOwnable: Sized { · 10 unmodified lines
27 const FOREIGN_ALIGN: usize;31 const FOREIGN_ALIGN: usize;
28 32
29 /// Type used to immutably borrow a value that is currently foreign-owned.33 /// Type used to immutably borrow a value that is currently foreign-owned.
30 type Borrowed<'a>;34 type Borrowed<'a>
35 where
36 Self: 'a;
31 37
32 /// Type used to mutably borrow a value that is currently foreign-owned.38 /// Type used to mutably borrow a value that is currently foreign-owned.
33 type BorrowedMut<'a>;39 type BorrowedMut<'a>
40 where
41 Self: 'a;
34 42
35 /// Converts a Rust-owned object to a foreign-owned one.43 /// Converts a Rust-owned object to a foreign-owned one.
36 ///44 ///
rust/kernel/types/for_lt.rs+122−0
@@ -0,0 +1,122 @@
1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3//! Provide implementation and test of the `ForLt` trait and macro.
4//!
5//! This module is hidden and user should just use `ForLt!` directly.
6
7use core::marker::PhantomData;
8
9/// Representation of types generic over a lifetime.
10///
11/// The type must be covariant over the generic lifetime, i.e. the lifetime parameter
12/// can be soundly shortened.
13///
14/// The lifetime involved must be covariant.
15///
16/// # Macro
17///
18/// It is not recommended to implement this trait directly. `ForLt!` macro is provided to obtain a
19/// type that implements this trait.
20///
21/// The full syntax is
22///
23/// ```
24/// # use kernel::types::ForLt;
25/// # fn expect_lt<F: ForLt>() {}
26/// # struct TypeThatUse<'a>(&'a ());
27/// # expect_lt::<
28/// ForLt!(for<'a> TypeThatUse<'a>)
29/// # >();
30/// ```
31///
32/// which gives a type so that `<ForLt!(for<'a> TypeThatUse<'a>) as ForLt>::Of<'b>`
33/// is `TypeThatUse<'b>`.
34///
35/// You may also use a short-hand syntax which works similar to lifetime elision.
36/// The macro also accepts types that do not involve a lifetime at all.
37///
38/// ```
39/// # use kernel::types::ForLt;
40/// # fn expect_lt<F: ForLt>() {}
41/// # struct TypeThatUse<'a>(&'a ());
42/// # expect_lt::<
43/// ForLt!(TypeThatUse<'_>) // Equivalent to `ForLt!(for<'a> TypeThatUse<'a>)`.
44/// # >();
45/// # expect_lt::<
46/// ForLt!(&u32) // Equivalent to `ForLt!(for<'a> &'a u32)`.
47/// # >();
48/// # expect_lt::<
49/// ForLt!(u32) // Equivalent to `ForLt!(for<'a> u32)`.
50/// # >();
51/// ```
52///
53/// The macro will attempt to prove that the type is indeed covariant over the lifetime supplied.
54/// When it cannot be syntactically proven, it will emit checks to ask the Rust compiler to prove
55/// it.
56///
57/// ```ignore,compile_fail
58/// # use kernel::types::ForLt;
59/// # fn expect_lt<F: ForLt>() {}
60/// # expect_lt::<
61/// ForLt!(fn(&u32)) // Contravariant, will fail compilation.
62/// # >();
63/// ```
64///
65/// There is a limitation if the type refers to generic parameters; if the macro cannot prove the
66/// covariance syntactically, the emitted checks will fail the compilation as it needs to refer to
67/// the generic parameter but is in a separate item.
68///
69/// ```
70/// # use kernel::types::ForLt;
71/// fn expect_lt<F: ForLt>() {}
72/// # #[allow(clippy::unnecessary_safety_comment, reason = "false positive")]
73/// fn generic_fn<T: 'static>() {
74/// // Syntactically proven by the macro
75/// expect_lt::<ForLt!(&T)>();
76/// // Syntactically proven by the macro
77/// expect_lt::<ForLt!(&KBox<T>)>();
78/// // Cannot be syntactically proven, need to check covariance of `KBox`
79/// // expect_lt::<ForLt!(&KBox<&T>)>();
80/// }
81/// ```
82///
83/// # Safety
84///
85/// `Self::Of<'a>` must be covariant over the lifetime `'a`.
86pub unsafe trait ForLt {
87 /// The type parameterized by the lifetime.
88 type Of<'a>: 'a;
89
90 /// Cast a reference to a shorter lifetime.
91 #[inline(always)]
92 fn cast_ref<'r, 'short: 'r, 'long: 'short>(long: &'r Self::Of<'long>) -> &'r Self::Of<'short> {
93 // SAFETY: This is sound as this trait guarantees covariance.
94 unsafe { core::mem::transmute(long) }
95 }
96}
97pub use macros::ForLt;
98
99/// This is intended to be an "unsafe-to-refer-to" type.
100///
101/// Must only be used by the `ForLt!` macro.
102///
103/// `T` is the magic `dyn for<'a> WithLt<'a, TypeThatUse<'a>>` generated by macro.
104///
105/// `WF` is a type that the macro can use to assert some specific type is well-formed.
106///
107/// `N` is to provide the macro a place to emit arbitrary items, in case it needs to prove
108/// additional properties.
109#[doc(hidden)]
110pub struct UnsafeForLtImpl<T: ?Sized, WF, const N: usize>(PhantomData<(WF, T)>);
111
112// This is a helper trait for implementation `ForLt` to be able to use HRTB.
113#[doc(hidden)]
114pub trait WithLt<'a> {
115 type Of: 'a;
116}
117
118// SAFETY: In `ForLt!` macro, a covariance proof is generated when naming `UnsafeForLtImpl`
119// and it will fail to evaluate if the type is not covariant.
120unsafe impl<T: ?Sized + for<'a> WithLt<'a>, WF> ForLt for UnsafeForLtImpl<T, WF, 0> {
121 type Of<'a> = <T as WithLt<'a>>::Of;
122}
rust/kernel/usb.rs+36−21
@@ -36,18 +36,18 @@ pub struct Adapter<T: Driver>(T); · 35 unmodified lines
36 36
37// SAFETY:37// SAFETY:
38// - `bindings::usb_driver` is a C type declared as `repr(C)`.38// - `bindings::usb_driver` is a C type declared as `repr(C)`.
39// - `T` is the type of the driver's device private data.39// - `T::Data` is the type of the driver's device private data.
40// - `struct usb_driver` embeds a `struct device_driver`.40// - `struct usb_driver` embeds a `struct device_driver`.
41// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.41// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `struct device_driver`.
42unsafe impl<T: Driver + 'static> driver::DriverLayout for Adapter<T> {42unsafe impl<T: Driver> driver::DriverLayout for Adapter<T> {
43 type DriverType = bindings::usb_driver;43 type DriverType = bindings::usb_driver;
44 type DriverData = T;44 type DriverData<'bound> = T::Data<'bound>;
45 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);45 const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, driver);
46}46}
47 47
48// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if48// SAFETY: A call to `unregister` for a given instance of `DriverType` is guaranteed to be valid if
49// a preceding call to `register` has been successful.49// a preceding call to `register` has been successful.
50unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {50unsafe impl<T: Driver> driver::RegistrationOps for Adapter<T> {
51 unsafe fn register(51 unsafe fn register(
52 udrv: &Opaque<Self::DriverType>,52 udrv: &Opaque<Self::DriverType>,
53 name: &'static CStr,53 name: &'static CStr,
@@ -73,7 +73,7 @@ unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { · 19 unmodified lines
73 }73 }
74}74}
75 75
76impl<T: Driver + 'static> Adapter<T> {76impl<T: Driver> Adapter<T> {
77 extern "C" fn probe_callback(77 extern "C" fn probe_callback(
78 intf: *mut bindings::usb_interface,78 intf: *mut bindings::usb_interface,
79 id: *const bindings::usb_device_id,79 id: *const bindings::usb_device_id,
@@ -82,7 +82,7 @@ impl<T: Driver + 'static> Adapter<T> { · 2 unmodified lines
82 // `struct usb_interface` and `struct usb_device_id`.82 // `struct usb_interface` and `struct usb_device_id`.
83 //83 //
84 // INVARIANT: `intf` is valid for the duration of `probe_callback()`.84 // INVARIANT: `intf` is valid for the duration of `probe_callback()`.
85 let intf = unsafe { &*intf.cast::<Interface<device::CoreInternal>>() };85 let intf = unsafe { &*intf.cast::<Interface<device::CoreInternal<'_>>>() };
86 86
87 from_result(|| {87 from_result(|| {
88 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct usb_device_id` and88 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct usb_device_id` and
@@ -92,7 +92,7 @@ impl<T: Driver + 'static> Adapter<T> { · 3 unmodified lines
92 let info = T::ID_TABLE.info(id.index());92 let info = T::ID_TABLE.info(id.index());
93 let data = T::probe(intf, id, info);93 let data = T::probe(intf, id, info);
94 94
95 let dev: &device::Device<device::CoreInternal> = intf.as_ref();95 let dev: &device::Device<device::CoreInternal<'_>> = intf.as_ref();
96 dev.set_drvdata(data)?;96 dev.set_drvdata(data)?;
97 Ok(0)97 Ok(0)
98 })98 })
@@ -103,14 +103,14 @@ impl<T: Driver + 'static> Adapter<T> { · 4 unmodified lines
103 // `struct usb_interface`.103 // `struct usb_interface`.
104 //104 //
105 // INVARIANT: `intf` is valid for the duration of `disconnect_callback()`.105 // INVARIANT: `intf` is valid for the duration of `disconnect_callback()`.
106 let intf = unsafe { &*intf.cast::<Interface<device::CoreInternal>>() };106 let intf = unsafe { &*intf.cast::<Interface<device::CoreInternal<'_>>>() };
107 107
108 let dev: &device::Device<device::CoreInternal> = intf.as_ref();108 let dev: &device::Device<device::CoreInternal<'_>> = intf.as_ref();
109 109
110 // SAFETY: `disconnect_callback` is only ever called after a successful call to110 // SAFETY: `disconnect_callback` is only ever called after a successful call to
111 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called111 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
112 // and stored a `Pin<KBox<T>>`.112 // and stored a `Pin<KBox<T::Data<'_>>>`.
113 let data = unsafe { dev.drvdata_borrow::<T>() };113 let data = unsafe { dev.drvdata_borrow::<T::Data<'_>>() };
114 114
115 T::disconnect(intf, data);115 T::disconnect(intf, data);
116 }116 }
@@ -287,23 +287,31 @@ macro_rules! usb_device_table { · 170 unmodified lines
287///287///
288/// impl usb::Driver for MyDriver {288/// impl usb::Driver for MyDriver {
289/// type IdInfo = ();289/// type IdInfo = ();
290/// type Data<'bound> = Self;
290/// const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE;291/// const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE;
291///292///
292/// fn probe(293/// fn probe<'bound>(
293/// _interface: &usb::Interface<Core>,294/// _interface: &'bound usb::Interface<Core<'_>>,
294/// _id: &usb::DeviceId,295/// _id: &usb::DeviceId,
295/// _info: &Self::IdInfo,296/// _info: &'bound Self::IdInfo,
296/// ) -> impl PinInit<Self, Error> {297/// ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
297/// Err(ENODEV)298/// Err(ENODEV)
298/// }299/// }
299///300///
300/// fn disconnect(_interface: &usb::Interface<Core>, _data: Pin<&Self>) {}301/// fn disconnect<'bound>(
302/// _interface: &'bound usb::Interface<Core<'_>>,
303/// _data: Pin<&Self::Data<'bound>>,
304/// ) {
305/// }
301/// }306/// }
302///```307///```
303pub trait Driver {308pub trait Driver {
304 /// The type holding information about each one of the device ids supported by the driver.309 /// The type holding information about each one of the device ids supported by the driver.
305 type IdInfo: 'static;310 type IdInfo: 'static;
306 311
312 /// The type of the driver's bus device private data.
313 type Data<'bound>: Send + 'bound;
314
307 /// The table of device ids supported by the driver.315 /// The table of device ids supported by the driver.
308 const ID_TABLE: IdTable<Self::IdInfo>;316 const ID_TABLE: IdTable<Self::IdInfo>;
309 317
@@ -311,16 +319,19 @@ pub trait Driver { · 1 unmodified line
311 ///319 ///
312 /// Called when a new USB interface is bound to this driver.320 /// Called when a new USB interface is bound to this driver.
313 /// Implementers should attempt to initialize the interface here.321 /// Implementers should attempt to initialize the interface here.
314 fn probe(322 fn probe<'bound>(
315 interface: &Interface<device::Core>,323 interface: &'bound Interface<device::Core<'_>>,
316 id: &DeviceId,324 id: &DeviceId,
317 id_info: &Self::IdInfo,325 id_info: &'bound Self::IdInfo,
318 ) -> impl PinInit<Self, Error>;326 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound;
319 327
320 /// USB driver disconnect.328 /// USB driver disconnect.
321 ///329 ///
322 /// Called when the USB interface is about to be unbound from this driver.330 /// Called when the USB interface is about to be unbound from this driver.
323 fn disconnect(interface: &Interface<device::Core>, data: Pin<&Self>);331 fn disconnect<'bound>(
332 interface: &'bound Interface<device::Core<'_>>,
333 data: Pin<&Self::Data<'bound>>,
334 );
324}335}
325 336
326/// A USB interface.337/// A USB interface.
@@ -464,6 +475,10 @@ unsafe impl Send for Device {} · 137 unmodified lines
464// allow any mutation through a shared reference.475// allow any mutation through a shared reference.
465unsafe impl Sync for Device {}476unsafe impl Sync for Device {}
466 477
478// SAFETY: Same as `Device<Normal>` -- the underlying `struct usb_device` is the same;
479// `Bound` is a zero-sized type-state marker that does not affect thread safety.
480unsafe impl Sync for Device<device::Bound> {}
481
467/// Declares a kernel module that exposes a single USB driver.482/// Declares a kernel module that exposes a single USB driver.
468///483///
469/// # Examples484/// # Examples
rust/macros/for_lt.rs+248−0
@@ -0,0 +1,248 @@
1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3use proc_macro2::{
4 Span,
5 TokenStream, //
6};
7use quote::{
8 format_ident,
9 quote, //
10};
11use syn::{
12 parse::{
13 Parse,
14 ParseStream, //
15 },
16 visit::Visit,
17 visit_mut::VisitMut,
18 Lifetime,
19 Result,
20 Token,
21 Type, //
22};
23
24pub(crate) enum HigherRankedType {
25 Explicit {
26 _for_token: Token![for],
27 _lt_token: Token![<],
28 lifetime: Lifetime,
29 _gt_token: Token![>],
30 ty: Type,
31 },
32 Implicit {
33 ty: Type,
34 },
35}
36
37impl Parse for HigherRankedType {
38 fn parse(input: ParseStream<'_>) -> Result<Self> {
39 if input.peek(Token![for]) {
40 Ok(Self::Explicit {
41 _for_token: input.parse()?,
42 _lt_token: input.parse()?,
43 lifetime: input.parse()?,
44 _gt_token: input.parse()?,
45 ty: input.parse()?,
46 })
47 } else {
48 Ok(Self::Implicit { ty: input.parse()? })
49 }
50 }
51}
52
53trait TypeExt {
54 fn expand_elided_lifetime(&self, explicit_lt: &Lifetime) -> Type;
55 fn replace_lifetime(&self, src: &Lifetime, dst: &Lifetime) -> Type;
56 fn has_lifetime(&self, lt: &Lifetime) -> bool;
57}
58
59impl TypeExt for Type {
60 fn expand_elided_lifetime(&self, explicit_lt: &Lifetime) -> Type {
61 struct ElidedLifetimeExpander<'a>(&'a Lifetime);
62
63 impl VisitMut for ElidedLifetimeExpander<'_> {
64 fn visit_lifetime_mut(&mut self, lifetime: &mut Lifetime) {
65 // Expand explicit `'_`
66 if lifetime.ident == "_" {
67 *lifetime = self.0.clone();
68 }
69 }
70
71 fn visit_type_reference_mut(&mut self, reference: &mut syn::TypeReference) {
72 syn::visit_mut::visit_type_reference_mut(self, reference);
73
74 if reference.lifetime.is_none() {
75 reference.lifetime = Some(self.0.clone());
76 }
77 }
78 }
79
80 let mut ret = self.clone();
81 ElidedLifetimeExpander(explicit_lt).visit_type_mut(&mut ret);
82 ret
83 }
84
85 fn replace_lifetime(&self, src: &Lifetime, dst: &Lifetime) -> Type {
86 struct LifetimeReplacer<'a>(&'a Lifetime, &'a Lifetime);
87
88 impl VisitMut for LifetimeReplacer<'_> {
89 fn visit_lifetime_mut(&mut self, lifetime: &mut Lifetime) {
90 if lifetime.ident == self.0.ident {
91 *lifetime = self.1.clone();
92 }
93 }
94 }
95
96 let mut ret = self.clone();
97 LifetimeReplacer(src, dst).visit_type_mut(&mut ret);
98 ret
99 }
100
101 fn has_lifetime(&self, lt: &Lifetime) -> bool {
102 struct HasLifetime<'a>(&'a Lifetime, bool);
103
104 impl Visit<'_> for HasLifetime<'_> {
105 fn visit_lifetime(&mut self, lifetime: &Lifetime) {
106 if lifetime.ident == self.0.ident {
107 self.1 = true;
108 }
109 }
110
111 // Macro invocations are opaque; conservatively assume they may
112 // reference the lifetime.
113 fn visit_macro(&mut self, _: &syn::Macro) {
114 self.1 = true;
115 }
116 }
117
118 let mut visitor = HasLifetime(lt, false);
119 visitor.visit_type(self);
120 visitor.1
121 }
122}
123
124struct Prover<'a>(&'a Lifetime, Vec<&'a Type>);
125
126impl<'a> Prover<'a> {
127 /// Prove that `ty` is covariant over `'lt`.
128 ///
129 /// This also needs to prove that it'll be wellformed for any instance of `'lt`.
130 /// It can be assumed that `ty` will be wellformed if `'lt` is substituted to `'static`.
131 fn prove(&mut self, ty: &'a Type) {
132 match ty {
133 Type::Paren(ty) => self.prove(&ty.elem),
134 Type::Group(ty) => self.prove(&ty.elem),
135
136 // No lifetime involved
137 Type::Never(_) => {}
138
139 // `[T; N]` and `[T]` is covariant over `T`.
140 Type::Array(ty) => self.prove(&ty.elem),
141 Type::Slice(ty) => self.prove(&ty.elem),
142
143 Type::Tuple(ty) => {
144 for elem in &ty.elems {
145 self.prove(elem);
146 }
147 }
148
149 // `*const T` is covariant over `T`
150 Type::Ptr(ty) if ty.const_token.is_some() => self.prove(&ty.elem),
151
152 // `&T` is covariant over `T` and lifetime.
153 //
154 // Note that if we encounter `&'other_lt T`, then we still need to make sure the type
155 // is wellformed if `T` involves `&'lt`, so we defer to the compiler.
156 //
157 // This is to block cases like `ForLt!(for<'a> &'static &'a u32)`, as the presence of
158 // the type implies `'a: 'static` but this is unsound.
159 Type::Reference(ty)
160 if ty.mutability.is_none() && ty.lifetime.as_ref() == Some(self.0) =>
161 {
162 self.prove(&ty.elem)
163 }
164
165 // `&[mut] T` is covariant over lifetime.
166 // In case we have `&[mut] NoLifetime`, we don't need to do additional checks.
167 Type::Reference(ty) if !ty.elem.has_lifetime(self.0) => (),
168
169 // No mention of lifetime at all, no need to perform compiler check.
170 ty if !ty.has_lifetime(self.0) => (),
171
172 // Otherwise, we need to emit checks so that compiler can determine if the types are
173 // actually covariant.
174 ty => self.1.push(ty),
175 }
176 }
177}
178
179pub(crate) fn for_lt(input: HigherRankedType) -> TokenStream {
180 let (ty, lifetime) = match input {
181 HigherRankedType::Explicit { lifetime, ty, .. } => (ty, lifetime),
182 HigherRankedType::Implicit { ty } => {
183 // If there's no explicit `for<'a>` binder, inject a synthetic `'__elided` lifetime
184 // and expand elided sites.
185 let lifetime = Lifetime {
186 apostrophe: Span::mixed_site(),
187 ident: format_ident!("__elided", span = Span::mixed_site()),
188 };
189 (ty.expand_elided_lifetime(&lifetime), lifetime)
190 }
191 };
192
193 let mut prover = Prover(&lifetime, Vec::new());
194 prover.prove(&ty);
195
196 let mut proof = Vec::new();
197
198 // Emit proofs for every type that requires additional compiler help in proving covariance.
199 for (idx, required_proof) in prover.1.into_iter().enumerate() {
200 // Insert a proof that the type is well-formed.
201 //
202 // This is intended to workaround a Rust compiler soundness bug related to HRTB.
203 // https://github.com/rust-lang/rust/issues/152489
204 //
205 // This needs to be a struct instead of fn to avoid the implied WF bounds.
206 let wf_proof_name = format_ident!("ProveWf{idx}");
207 proof.push(quote!(
208 struct #wf_proof_name<#lifetime>(
209 ::core::marker::PhantomData<&#lifetime ()>, #required_proof
210 );
211 ));
212
213 // Insert a proof that the type is covariant.
214 let cov_proof_name = format_ident!("prove_covariant_{idx}");
215 proof.push(quote!(
216 fn #cov_proof_name<'__short, '__long: '__short>(
217 long: #wf_proof_name<'__long>
218 ) -> #wf_proof_name<'__short> {
219 long
220 }
221 ));
222 }
223
224 // Make sure that the type is wellformed when substituting lifetime with `'static`.
225 //
226 // Currently the Rust compiler doesn't check this, see the above `ProveWf` documentation.
227 //
228 // We prefer to use this way of proving WF-ness as it can work when generics are involved.
229 let ty_static = ty.replace_lifetime(
230 &lifetime,
231 &Lifetime {
232 apostrophe: Span::mixed_site(),
233 ident: format_ident!("static"),
234 },
235 );
236
237 quote!(
238 ::kernel::types::for_lt::UnsafeForLtImpl::<
239 dyn for<#lifetime> ::kernel::types::for_lt::WithLt<#lifetime, Of = #ty>,
240 #ty_static,
241 {
242 #(#proof)*
243
244 0
245 }
246 >
247 )
248}
rust/macros/lib.rs+13−0
@@ -17,6 +17,7 @@ · 16 unmodified lines
17mod concat_idents;17mod concat_idents;
18mod export;18mod export;
19mod fmt;19mod fmt;
20mod for_lt;
20mod helpers;21mod helpers;
21mod kunit;22mod kunit;
22mod module;23mod module;
@@ -489,3 +490,15 @@ pub fn kunit_tests(attr: TokenStream, input: TokenStream) -> TokenStream { · 466 unmodified lines
489 .unwrap_or_else(|e| e.into_compile_error())490 .unwrap_or_else(|e| e.into_compile_error())
490 .into()491 .into()
491}492}
493
494/// Obtain a type that implements [`ForLt`] for the given higher-ranked type.
495///
496/// Please refer to the documentation of the [`ForLt`] trait.
497///
498/// [`ForLt`]: trait.ForLt.html
499#[proc_macro]
500// The macro shares the name with the trait.
501#[allow(non_snake_case)]
502pub fn ForLt(input: TokenStream) -> TokenStream {
503 for_lt::for_lt(parse_macro_input!(input)).into()
504}
samples/rust/rust_debugfs.rs+6−5
@@ -117,13 +117,14 @@ kernel::acpi_device_table!( · 116 unmodified lines
117 117
118impl platform::Driver for RustDebugFs {118impl platform::Driver for RustDebugFs {
119 type IdInfo = ();119 type IdInfo = ();
120 type Data<'bound> = Self;
120 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;121 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
121 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);122 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
122 123
123 fn probe(124 fn probe<'bound>(
124 pdev: &platform::Device<Core>,125 pdev: &'bound platform::Device<Core<'_>>,
125 _info: Option<&Self::IdInfo>,126 _info: Option<&'bound Self::IdInfo>,
126 ) -> impl PinInit<Self, Error> {127 ) -> impl PinInit<Self, Error> + 'bound {
127 RustDebugFs::new(pdev).pin_chain(|this| {128 RustDebugFs::new(pdev).pin_chain(|this| {
128 this.counter.store(91, Relaxed);129 this.counter.store(91, Relaxed);
129 {130 {
@@ -146,7 +147,7 @@ impl RustDebugFs { · 16 unmodified lines
146 dir.read_write_file(c"pair", new_mutex!(Inner { x: 3, y: 10 }))147 dir.read_write_file(c"pair", new_mutex!(Inner { x: 3, y: 10 }))
147 }148 }
148 149
149 fn new(pdev: &platform::Device<Core>) -> impl PinInit<Self, Error> + '_ {150 fn new<'a>(pdev: &'a platform::Device<Core<'_>>) -> impl PinInit<Self, Error> + 'a {
150 let debugfs = Dir::new(c"sample_debugfs");151 let debugfs = Dir::new(c"sample_debugfs");
151 let dev = pdev.as_ref();152 let dev = pdev.as_ref();
152 153
samples/rust/rust_dma.rs+5−1
@@ -58,9 +58,13 @@ kernel::pci_device_table!( · 57 unmodified lines
58 58
59impl pci::Driver for DmaSampleDriver {59impl pci::Driver for DmaSampleDriver {
60 type IdInfo = ();60 type IdInfo = ();
61 type Data<'bound> = Self;
61 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;62 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
62 63
63 fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {64 fn probe<'bound>(
65 pdev: &'bound pci::Device<Core<'_>>,
66 _info: &'bound Self::IdInfo,
67 ) -> impl PinInit<Self, Error> + 'bound {
64 pin_init::pin_init_scope(move || {68 pin_init::pin_init_scope(move || {
65 dev_info!(pdev, "Probe DMA test driver.\n");69 dev_info!(pdev, "Probe DMA test driver.\n");
66 70
samples/rust/rust_driver_auxiliary.rs+56−23
@@ -10,15 +10,13 @@ use kernel::{ · 9 unmodified lines
10 Bound,10 Bound,
11 Core, //11 Core, //
12 },12 },
13 devres::Devres,
14 driver,13 driver,
15 pci,14 pci,
16 prelude::*,15 prelude::*,
16 types::ForLt,
17 InPlaceModule, //17 InPlaceModule, //
18};18};
19 19
20use core::any::TypeId;
21
22const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;20const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME;
23const AUXILIARY_NAME: &CStr = c"auxiliary";21const AUXILIARY_NAME: &CStr = c"auxiliary";
24 22
@@ -33,10 +31,14 @@ kernel::auxiliary_device_table!( · 8 unmodified lines
33 31
34impl auxiliary::Driver for AuxiliaryDriver {32impl auxiliary::Driver for AuxiliaryDriver {
35 type IdInfo = ();33 type IdInfo = ();
34 type Data<'bound> = Self;
36 35
37 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;36 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
38 37
39 fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {38 fn probe<'bound>(
39 adev: &'bound auxiliary::Device<Core<'_>>,
40 _info: &'bound Self::IdInfo,
41 ) -> impl PinInit<Self, Error> + 'bound {
40 dev_info!(42 dev_info!(
41 adev,43 adev,
42 "Probing auxiliary driver for auxiliary device with id={}\n",44 "Probing auxiliary driver for auxiliary device with id={}\n",
@@ -49,13 +51,17 @@ impl auxiliary::Driver for AuxiliaryDriver { · 6 unmodified lines
49 }51 }
50}52}
51 53
52#[pin_data]54struct Data<'bound> {
53struct ParentDriver {55 index: u32,
54 private: TypeId,56 parent: &'bound pci::Device<Bound>,
55 #[pin]57}
56 _reg0: Devres<auxiliary::Registration>,58
57 #[pin]59struct ParentDriver;
58 _reg1: Devres<auxiliary::Registration>,60
61#[allow(clippy::type_complexity)]
62struct ParentData<'bound> {
63 _reg0: auxiliary::Registration<'bound, ForLt!(Data<'_>)>,
64 _reg1: auxiliary::Registration<'bound, ForLt!(Data<'_>)>,
59}65}
60 66
61kernel::pci_device_table!(67kernel::pci_device_table!(
@@ -67,26 +73,53 @@ kernel::pci_device_table!( · 5 unmodified lines
67 73
68impl pci::Driver for ParentDriver {74impl pci::Driver for ParentDriver {
69 type IdInfo = ();75 type IdInfo = ();
76 type Data<'bound> = ParentData<'bound>;
70 77
71 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;78 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
72 79
73 fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {80 fn probe<'bound>(
74 try_pin_init!(Self {81 pdev: &'bound pci::Device<Core<'_>>,
75 private: TypeId::of::<Self>(),82 _info: &'bound Self::IdInfo,
76 _reg0 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME),83 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
77 _reg1 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME),84 Ok(ParentData {
85 // SAFETY: `ParentData` is the driver's private data, which is dropped when the
86 // device is unbound; i.e. `mem::forget()` is never called on it.
87 _reg0: unsafe {
88 auxiliary::Registration::new_with_lt(
89 pdev.as_ref(),
90 AUXILIARY_NAME,
91 0,
92 MODULE_NAME,
93 Data {
94 index: 0,
95 parent: pdev,
96 },
97 )?
98 },
99 // SAFETY: See `_reg0` above.
100 _reg1: unsafe {
101 auxiliary::Registration::new_with_lt(
102 pdev.as_ref(),
103 AUXILIARY_NAME,
104 1,
105 MODULE_NAME,
106 Data {
107 index: 1,
108 parent: pdev,
109 },
110 )?
111 },
78 })112 })
79 }113 }
80}114}
81 115
82impl ParentDriver {116impl ParentDriver {
83 fn connect(adev: &auxiliary::Device<Bound>) -> Result {117 fn connect(adev: &auxiliary::Device<Bound>) -> Result {
84 let dev = adev.parent();118 let data = adev.registration_data::<ForLt!(Data<'_>)>()?;
85 let pdev: &pci::Device<Bound> = dev.try_into()?;119 let pdev = data.parent;
86 let drvdata = dev.drvdata::<Self>()?;
87 120
88 dev_info!(121 dev_info!(
89 dev,122 pdev,
90 "Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n",123 "Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n",
91 adev.id(),124 adev.id(),
92 pdev.vendor_id(),125 pdev.vendor_id(),
@@ -94,9 +127,9 @@ impl ParentDriver { · 1 unmodified line
94 );127 );
95 128
96 dev_info!(129 dev_info!(
97 dev,130 pdev,
98 "We have access to the private data of {:?}.\n",131 "Connected to auxiliary device with index {}.\n",
99 drvdata.private132 data.index
100 );133 );
101 134
102 Ok(())135 Ok(())
samples/rust/rust_driver_i2c.rs+7−6
@@ -35,15 +35,16 @@ kernel::of_device_table! { · 34 unmodified lines
35 35
36impl i2c::Driver for SampleDriver {36impl i2c::Driver for SampleDriver {
37 type IdInfo = u32;37 type IdInfo = u32;
38 type Data<'bound> = Self;
38 39
39 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);40 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
40 const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE);41 const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE);
41 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);42 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
42 43
43 fn probe(44 fn probe<'bound>(
44 idev: &i2c::I2cClient<Core>,45 idev: &'bound i2c::I2cClient<Core<'_>>,
45 info: Option<&Self::IdInfo>,46 info: Option<&'bound Self::IdInfo>,
46 ) -> impl PinInit<Self, Error> {47 ) -> impl PinInit<Self, Error> + 'bound {
47 let dev = idev.as_ref();48 let dev = idev.as_ref();
48 49
49 dev_info!(dev, "Probe Rust I2C driver sample.\n");50 dev_info!(dev, "Probe Rust I2C driver sample.\n");
@@ -55,11 +56,11 @@ impl i2c::Driver for SampleDriver { · 5 unmodified lines
55 Ok(Self)56 Ok(Self)
56 }57 }
57 58
58 fn shutdown(idev: &i2c::I2cClient<Core>, _this: Pin<&Self>) {59 fn shutdown<'bound>(idev: &'bound i2c::I2cClient<Core<'_>>, _this: Pin<&Self>) {
59 dev_info!(idev.as_ref(), "Shutdown Rust I2C driver sample.\n");60 dev_info!(idev.as_ref(), "Shutdown Rust I2C driver sample.\n");
60 }61 }
61 62
62 fn unbind(idev: &i2c::I2cClient<Core>, _this: Pin<&Self>) {63 fn unbind<'bound>(idev: &'bound i2c::I2cClient<Core<'_>>, _this: Pin<&Self>) {
63 dev_info!(idev.as_ref(), "Unbind Rust I2C driver sample.\n");64 dev_info!(idev.as_ref(), "Unbind Rust I2C driver sample.\n");
64 }65 }
65}66}
samples/rust/rust_driver_pci.rs+43−47
@@ -9,7 +9,6 @@ use kernel::{ · 8 unmodified lines
9 Bound,9 Bound,
10 Core, //10 Core, //
11 },11 },
12 devres::Devres,
13 io::{12 io::{
14 register,13 register,
15 register::Array,14 register::Array,
@@ -17,8 +16,7 @@ use kernel::{ · 1 unmodified line
17 },16 },
18 num::Bounded,17 num::Bounded,
19 pci,18 pci,
20 prelude::*,19 prelude::*, //
21 sync::aref::ARef, //
22};20};
23 21
24mod regs {22mod regs {
@@ -45,7 +43,7 @@ mod regs { · 20 unmodified lines
45 pub(super) const END: usize = 0x10;43 pub(super) const END: usize = 0x10;
46}44}
47 45
48type Bar0 = pci::Bar<{ regs::END }>;46type Bar0<'bound> = pci::Bar<'bound, { regs::END }>;
49 47
50#[derive(Copy, Clone, Debug)]48#[derive(Copy, Clone, Debug)]
51struct TestIndex(u8);49struct TestIndex(u8);
@@ -66,14 +64,14 @@ impl TestIndex { · 14 unmodified lines
66 const NO_EVENTFD: Self = Self(0);64 const NO_EVENTFD: Self = Self(0);
67}65}
68 66
69#[pin_data(PinnedDrop)]67struct SampleDriverData<'bound> {
70struct SampleDriver {68 pdev: &'bound pci::Device,
71 pdev: ARef<pci::Device>,69 bar: Bar0<'bound>,
72 #[pin]
73 bar: Devres<Bar0>,
74 index: TestIndex,70 index: TestIndex,
75}71}
76 72
73struct SampleDriver;
74
77kernel::pci_device_table!(75kernel::pci_device_table!(
78 PCI_TABLE,76 PCI_TABLE,
79 MODULE_PCI_TABLE,77 MODULE_PCI_TABLE,
@@ -84,8 +82,8 @@ kernel::pci_device_table!( · 4 unmodified lines
84 )]82 )]
85);83);
86 84
87impl SampleDriver {85impl SampleDriverData<'_> {
88 fn testdev(index: &TestIndex, bar: &Bar0) -> Result<u32> {86 fn testdev(index: &TestIndex, bar: &Bar0<'_>) -> Result<u32> {
89 // Select the test.87 // Select the test.
90 bar.write_reg(regs::TEST::zeroed().with_index(*index));88 bar.write_reg(regs::TEST::zeroed().with_index(*index));
91 89
@@ -140,51 +138,49 @@ impl SampleDriver { · 48 unmodified lines
140 138
141impl pci::Driver for SampleDriver {139impl pci::Driver for SampleDriver {
142 type IdInfo = TestIndex;140 type IdInfo = TestIndex;
141 type Data<'bound> = SampleDriverData<'bound>;
143 142
144 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;143 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
145 144
146 fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> {145 fn probe<'bound>(
147 pin_init::pin_init_scope(move || {146 pdev: &'bound pci::Device<Core<'_>>,
148 let vendor = pdev.vendor_id();147 info: &'bound Self::IdInfo,
149 dev_dbg!(148 ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
150 pdev,149 let vendor = pdev.vendor_id();
151 "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n",150 dev_dbg!(
152 vendor,151 pdev,
153 pdev.device_id()152 "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n",
154 );153 vendor,
155 154 pdev.device_id()
156 pdev.enable_device_mem()?;155 );
157 pdev.set_master();156
158 157 pdev.enable_device_mem()?;
159 Ok(try_pin_init!(Self {158 pdev.set_master();
160 bar <- pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_driver_pci"),159
161 index: *info,160 let bar = pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_driver_pci")?;
162 _: {161
163 let bar = bar.access(pdev.as_ref())?;162 dev_info!(
164 163 pdev,
165 dev_info!(164 "pci-testdev data-match count: {}\n",
166 pdev,165 SampleDriverData::testdev(info, &bar)?
167 "pci-testdev data-match count: {}\n",166 );
168 Self::testdev(info, bar)?167 SampleDriverData::config_space(pdev);
169 );168
170 Self::config_space(pdev);169 Ok(SampleDriverData {
171 },170 pdev,
172 pdev: pdev.into(),171 bar,
173 }))172 index: *info,
174 })173 })
175 }174 }
176 175
177 fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {176 fn unbind<'bound>(_pdev: &'bound pci::Device<Core<'_>>, this: Pin<&Self::Data<'bound>>) {
178 if let Ok(bar) = this.bar.access(pdev.as_ref()) {177 this.bar
179 // Reset pci-testdev by writing a new test index.178 .write_reg(regs::TEST::zeroed().with_index(this.index));
180 bar.write_reg(regs::TEST::zeroed().with_index(this.index));
181 }
182 }179 }
183}180}
184 181
185#[pinned_drop]182impl Drop for SampleDriverData<'_> {
186impl PinnedDrop for SampleDriver {183 fn drop(&mut self) {
187 fn drop(self: Pin<&mut Self>) {
188 dev_dbg!(self.pdev, "Remove Rust PCI driver sample.\n");184 dev_dbg!(self.pdev, "Remove Rust PCI driver sample.\n");
189 }185 }
190}186}
samples/rust/rust_driver_platform.rs+5−4
@@ -101,13 +101,14 @@ kernel::acpi_device_table!( · 100 unmodified lines
101 101
102impl platform::Driver for SampleDriver {102impl platform::Driver for SampleDriver {
103 type IdInfo = Info;103 type IdInfo = Info;
104 type Data<'bound> = Self;
104 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);105 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
105 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);106 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
106 107
107 fn probe(108 fn probe<'bound>(
108 pdev: &platform::Device<Core>,109 pdev: &'bound platform::Device<Core<'_>>,
109 info: Option<&Self::IdInfo>,110 info: Option<&'bound Self::IdInfo>,
110 ) -> impl PinInit<Self, Error> {111 ) -> impl PinInit<Self, Error> + 'bound {
111 let dev = pdev.as_ref();112 let dev = pdev.as_ref();
112 113
113 dev_dbg!(dev, "Probe Rust Platform driver sample.\n");114 dev_dbg!(dev, "Probe Rust Platform driver sample.\n");
samples/rust/rust_driver_usb.rs+8−7
@@ -26,21 +26,22 @@ kernel::usb_device_table!( · 25 unmodified lines
26 26
27impl usb::Driver for SampleDriver {27impl usb::Driver for SampleDriver {
28 type IdInfo = ();28 type IdInfo = ();
29 type Data<'bound> = Self;
29 const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE;30 const ID_TABLE: usb::IdTable<Self::IdInfo> = &USB_TABLE;
30 31
31 fn probe(32 fn probe<'bound>(
32 intf: &usb::Interface<Core>,33 intf: &'bound usb::Interface<Core<'_>>,
33 _id: &usb::DeviceId,34 _id: &usb::DeviceId,
34 _info: &Self::IdInfo,35 _info: &'bound Self::IdInfo,
35 ) -> impl PinInit<Self, Error> {36 ) -> impl PinInit<Self, Error> + 'bound {
36 let dev: &device::Device<Core> = intf.as_ref();37 let dev: &device::Device<Core<'_>> = intf.as_ref();
37 dev_info!(dev, "Rust USB driver sample probed\n");38 dev_info!(dev, "Rust USB driver sample probed\n");
38 39
39 Ok(Self { _intf: intf.into() })40 Ok(Self { _intf: intf.into() })
40 }41 }
41 42
42 fn disconnect(intf: &usb::Interface<Core>, _data: Pin<&Self>) {43 fn disconnect<'bound>(intf: &'bound usb::Interface<Core<'_>>, _data: Pin<&Self>) {
43 let dev: &device::Device<Core> = intf.as_ref();44 let dev: &device::Device<Core<'_>> = intf.as_ref();
44 dev_info!(dev, "Rust USB driver sample disconnected\n");45 dev_info!(dev, "Rust USB driver sample disconnected\n");
45 }46 }
46}47}
samples/rust/rust_i2c_client.rs+9−5
@@ -106,13 +106,14 @@ const BOARD_INFO: i2c::I2cBoardInfo = · 105 unmodified lines
106 106
107impl platform::Driver for SampleDriver {107impl platform::Driver for SampleDriver {
108 type IdInfo = ();108 type IdInfo = ();
109 type Data<'bound> = Self;
109 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);110 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
110 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);111 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
111 112
112 fn probe(113 fn probe<'bound>(
113 pdev: &platform::Device<device::Core>,114 pdev: &'bound platform::Device<device::Core<'_>>,
114 _info: Option<&Self::IdInfo>,115 _info: Option<&'bound Self::IdInfo>,
115 ) -> impl PinInit<Self, Error> {116 ) -> impl PinInit<Self, Error> + 'bound {
116 dev_info!(117 dev_info!(
117 pdev.as_ref(),118 pdev.as_ref(),
118 "Probe Rust I2C Client registration sample.\n"119 "Probe Rust I2C Client registration sample.\n"
@@ -129,7 +130,10 @@ impl platform::Driver for SampleDriver { · 10 unmodified lines
129 })130 })
130 }131 }
131 132
132 fn unbind(pdev: &platform::Device<device::Core>, _this: Pin<&Self>) {133 fn unbind<'bound>(
134 pdev: &'bound platform::Device<device::Core<'_>>,
135 _this: Pin<&Self::Data<'bound>>,
136 ) {
133 dev_info!(137 dev_info!(
134 pdev.as_ref(),138 pdev.as_ref(),
135 "Unbind Rust I2C Client registration sample.\n"139 "Unbind Rust I2C Client registration sample.\n"
samples/rust/rust_soc.rs+5−4
@@ -37,13 +37,14 @@ kernel::acpi_device_table!( · 36 unmodified lines
37 37
38impl platform::Driver for SampleSocDriver {38impl platform::Driver for SampleSocDriver {
39 type IdInfo = ();39 type IdInfo = ();
40 type Data<'bound> = Self;
40 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);41 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
41 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);42 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
42 43
43 fn probe(44 fn probe<'bound>(
44 pdev: &platform::Device<Core>,45 pdev: &'bound platform::Device<Core<'_>>,
45 _info: Option<&Self::IdInfo>,46 _info: Option<&'bound Self::IdInfo>,
46 ) -> impl PinInit<Self, Error> {47 ) -> impl PinInit<Self, Error> + 'bound {
47 dev_dbg!(pdev, "Probe Rust SoC driver sample.\n");48 dev_dbg!(pdev, "Probe Rust SoC driver sample.\n");
48 49
49 let pdev = pdev.into();50 let pdev = pdev.into();