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

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull driver core updates from Danilo Krummrich:
"Arch Topology:
- Move parse_acpi_topology() from arm64 to common code for reuse in
RISC-V

CPU:
- Expose housekeeping CPUs through /sys/devices/system/cpu/housekeeping
- Print a newline (or 0x0A) instead of '(null)' reading
/sys/devices/system/cpu/nohz_full when nohz_full= is not set

debugfs
- Remove (broken) 'no-mount' mode
- Remove redundant access mode checks in debugfs_get_tree() and
debugfs_create_*() functions

Devres:
- Remove unused devm_free_percpu() helper
- Move devm_alloc_percpu() from device.h to devres.h

Firmware Loader:
- Replace simple_strtol() with kstrtoint()
- Do not call cancel_store() when no upload is in progress

kernfs:
- Increase struct super_block::maxbytes to MAX_LFS_FILESIZE
- Fix a missing unwind path in __kernfs_new_node()

Misc:
- Increase the name size in struct auxiliary_device_id to 40
characters
- Replace system_unbound_wq with system_dfl_wq and add WQ_PERCPU to
alloc_workqueue()

Platform:
- Replace ERR_PTR() with IOMEM_ERR_PTR() in platform ioremap
functions

Rust:
- Auxiliary:
- Unregister auxiliary device on parent device unbind
- Move parent() to impl Device; implement device context aware
parent() for Device<Bound>
- Illustrate how to safely obtain a driver's device private data
when calling from an auxiliary driver into the parant device
driver

- DebugFs:
- Implement support for binary large objects

- Device:
- Let probe() return the driver's device private data as pinned
initializer, i.e. impl PinInit<Self, Error>
- Implement safe accessor for a driver's device private data for
Device<Bound> (returned reference can't out-live driver binding
and guarantees the correct private data type)
- Implement AsBusDevice trait, to be used by class device
abstractions to derive the bus device type of the parent device

- DMA:
- Store raw pointer of allocation as NonNull
- Use start_ptr() and start_ptr_mut() to inherit correct
mutability of self

- FS:
- Add file::Offset type alias

- I2C:
- Add abstractions for I2C device / driver infrastructure
- Implement abstractions for manual I2C device registrations

- I/O:
- Use "kernel vertical" style for imports
- Define ResourceSize as resource_size_t
- Move ResourceSize to top-level I/O module
- Add type alias for phys_addr_t
- Implement Rust version of read_poll_timeout_atomic()

- PCI:
- Use "kernel vertical" style for imports
- Move I/O and IRQ infrastructure to separate files
- Add support for PCI interrupt vectors
- Implement TryInto<IrqRequest<'a>> for IrqVector<'a> to convert
an IrqVector bound to specific pci::Device into an IrqRequest
bound to the same pci::Device's parent Device
- Leverage pin_init_scope() to get rid of redundant Result in IRQ
methods

- PinInit:
- Add {pin_}init_scope() to execute code before creating an
initializer

- Platform:
- Leverage pin_init_scope() to get rid of redundant Result in IRQ
methods

- Timekeeping:
- Implement abstraction of udelay()

- Uaccess:
- Implement read_slice_partial() and read_slice_file() for
UserSliceReader
- Implement write_slice_partial() and write_slice_file() for
UserSliceWriter

sysfs:
- Prepare the constification of struct attribute"

* tag 'driver-core-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: (75 commits)
rust: pci: fix build failure when CONFIG_PCI_MSI is disabled
debugfs: Fix default access mode config check
debugfs: Remove broken no-mount mode
debugfs: Remove redundant access mode checks
driver core: Check drivers_autoprobe for all added devices
driver core: WQ_PERCPU added to alloc_workqueue users
driver core: replace use of system_unbound_wq with system_dfl_wq
tick/nohz: Expose housekeeping CPUs in sysfs
tick/nohz: avoid showing '(null)' if nohz_full= not set
sysfs/cpu: Use DEVICE_ATTR_RO for nohz_full attribute
kernfs: fix memory leak of kernfs_iattrs in __kernfs_new_node
fs/kernfs: raise sb->maxbytes to MAX_LFS_FILESIZE
mod_devicetable: Bump auxiliary_device_id name size
sysfs: simplify attribute definition macros
samples/kobject: constify 'struct foo_attribute'
samples/kobject: add is_visible() callback to attribute group
sysfs: attribute_group: enable const variants of is_visible()
sysfs: introduce __SYSFS_FUNCTION_ALTERNATIVE()
sysfs: transparently handle const pointers in ATTRIBUTE_GROUPS()
sysfs: attribute_group: allow registration of const attribute
...

+2872 -700
+11
Documentation/ABI/testing/sysfs-devices-system-cpu
··· 764 764 participate in load balancing. These CPUs are set by 765 765 boot parameter "isolcpus=". 766 766 767 + What: /sys/devices/system/cpu/housekeeping 768 + Date: Oct 2025 769 + Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org> 770 + Description: 771 + (RO) the list of logical CPUs that are designated by the kernel as 772 + "housekeeping". Each CPU are responsible for handling essential 773 + system-wide background tasks, including RCU callbacks, delayed 774 + timer callbacks, and unbound workqueues, minimizing scheduling 775 + jitter on low-latency, isolated CPUs. These CPUs are set when boot 776 + parameter "isolcpus=nohz" or "nohz_full=" is specified. 777 + 767 778 What: /sys/devices/system/cpu/crash_hotplug 768 779 Date: Aug 2023 769 780 Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
+1 -5
Documentation/admin-guide/kernel-parameters.txt
··· 1211 1211 1212 1212 debugfs= [KNL,EARLY] This parameter enables what is exposed to 1213 1213 userspace and debugfs internal clients. 1214 - Format: { on, no-mount, off } 1214 + Format: { on, off } 1215 1215 on: All functions are enabled. 1216 - no-mount: 1217 - Filesystem is not registered but kernel clients can 1218 - access APIs and a crashkernel can be used to read 1219 - its content. There is nothing to mount. 1220 1216 off: Filesystem is not registered and clients 1221 1217 get a -EPERM as result when trying to register files 1222 1218 or directories within debugfs.
-1
Documentation/driver-api/driver-model/devres.rst
··· 383 383 384 384 PER-CPU MEM 385 385 devm_alloc_percpu() 386 - devm_free_percpu() 387 386 388 387 PCI 389 388 devm_pci_alloc_host_bridge() : managed PCI host bridge allocation
+10
MAINTAINERS
··· 11821 11821 F: include/uapi/linux/i2c-*.h 11822 11822 F: include/uapi/linux/i2c.h 11823 11823 11824 + I2C SUBSYSTEM [RUST] 11825 + M: Igor Korotin <igor.korotin.linux@gmail.com> 11826 + R: Danilo Krummrich <dakr@kernel.org> 11827 + R: Daniel Almeida <daniel.almeida@collabora.com> 11828 + L: rust-for-linux@vger.kernel.org 11829 + S: Maintained 11830 + F: rust/kernel/i2c.rs 11831 + F: samples/rust/rust_driver_i2c.rs 11832 + F: samples/rust/rust_i2c_client.rs 11833 + 11824 11834 I2C SUBSYSTEM HOST DRIVERS 11825 11835 M: Andi Shyti <andi.shyti@kernel.org> 11826 11836 L: linux-i2c@vger.kernel.org
+3
arch/arm64/include/asm/topology.h
··· 36 36 #define arch_scale_hw_pressure topology_get_hw_pressure 37 37 #define arch_update_hw_pressure topology_update_hw_pressure 38 38 39 + #undef arch_cpu_is_threaded 40 + #define arch_cpu_is_threaded() (read_cpuid_mpidr() & MPIDR_MT_BITMASK) 41 + 39 42 #include <asm-generic/topology.h> 40 43 41 44 #endif /* _ASM_ARM_TOPOLOGY_H */
-101
arch/arm64/kernel/topology.c
··· 25 25 #include <asm/cputype.h> 26 26 #include <asm/topology.h> 27 27 28 - #ifdef CONFIG_ACPI 29 - static bool __init acpi_cpu_is_threaded(int cpu) 30 - { 31 - int is_threaded = acpi_pptt_cpu_is_thread(cpu); 32 - 33 - /* 34 - * if the PPTT doesn't have thread information, assume a homogeneous 35 - * machine and return the current CPU's thread state. 36 - */ 37 - if (is_threaded < 0) 38 - is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK; 39 - 40 - return !!is_threaded; 41 - } 42 - 43 - struct cpu_smt_info { 44 - unsigned int thread_num; 45 - int core_id; 46 - }; 47 - 48 - /* 49 - * Propagate the topology information of the processor_topology_node tree to the 50 - * cpu_topology array. 51 - */ 52 - int __init parse_acpi_topology(void) 53 - { 54 - unsigned int max_smt_thread_num = 1; 55 - struct cpu_smt_info *entry; 56 - struct xarray hetero_cpu; 57 - unsigned long hetero_id; 58 - int cpu, topology_id; 59 - 60 - if (acpi_disabled) 61 - return 0; 62 - 63 - xa_init(&hetero_cpu); 64 - 65 - for_each_possible_cpu(cpu) { 66 - topology_id = find_acpi_cpu_topology(cpu, 0); 67 - if (topology_id < 0) 68 - return topology_id; 69 - 70 - if (acpi_cpu_is_threaded(cpu)) { 71 - cpu_topology[cpu].thread_id = topology_id; 72 - topology_id = find_acpi_cpu_topology(cpu, 1); 73 - cpu_topology[cpu].core_id = topology_id; 74 - 75 - /* 76 - * In the PPTT, CPUs below a node with the 'identical 77 - * implementation' flag have the same number of threads. 78 - * Count the number of threads for only one CPU (i.e. 79 - * one core_id) among those with the same hetero_id. 80 - * See the comment of find_acpi_cpu_topology_hetero_id() 81 - * for more details. 82 - * 83 - * One entry is created for each node having: 84 - * - the 'identical implementation' flag 85 - * - its parent not having the flag 86 - */ 87 - hetero_id = find_acpi_cpu_topology_hetero_id(cpu); 88 - entry = xa_load(&hetero_cpu, hetero_id); 89 - if (!entry) { 90 - entry = kzalloc(sizeof(*entry), GFP_KERNEL); 91 - WARN_ON_ONCE(!entry); 92 - 93 - if (entry) { 94 - entry->core_id = topology_id; 95 - entry->thread_num = 1; 96 - xa_store(&hetero_cpu, hetero_id, 97 - entry, GFP_KERNEL); 98 - } 99 - } else if (entry->core_id == topology_id) { 100 - entry->thread_num++; 101 - } 102 - } else { 103 - cpu_topology[cpu].thread_id = -1; 104 - cpu_topology[cpu].core_id = topology_id; 105 - } 106 - topology_id = find_acpi_cpu_topology_cluster(cpu); 107 - cpu_topology[cpu].cluster_id = topology_id; 108 - topology_id = find_acpi_cpu_topology_package(cpu); 109 - cpu_topology[cpu].package_id = topology_id; 110 - } 111 - 112 - /* 113 - * This is a short loop since the number of XArray elements is the 114 - * number of heterogeneous CPU clusters. On a homogeneous system 115 - * there's only one entry in the XArray. 116 - */ 117 - xa_for_each(&hetero_cpu, hetero_id, entry) { 118 - max_smt_thread_num = max(max_smt_thread_num, entry->thread_num); 119 - xa_erase(&hetero_cpu, hetero_id); 120 - kfree(entry); 121 - } 122 - 123 - cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num); 124 - xa_destroy(&hetero_cpu); 125 - return 0; 126 - } 127 - #endif 128 - 129 28 #ifdef CONFIG_ARM64_AMU_EXTN 130 29 #define read_corecnt() read_sysreg_s(SYS_AMEVCNTR0_CORE_EL0) 131 30 #define read_constcnt() read_sysreg_s(SYS_AMEVCNTR0_CONST_EL0)
+95 -1
drivers/base/arch_topology.c
··· 823 823 clear_cpu_topology(cpu); 824 824 } 825 825 826 + #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) 827 + struct cpu_smt_info { 828 + unsigned int thread_num; 829 + int core_id; 830 + }; 831 + 832 + static bool __init acpi_cpu_is_threaded(int cpu) 833 + { 834 + int is_threaded = acpi_pptt_cpu_is_thread(cpu); 835 + 836 + /* 837 + * if the PPTT doesn't have thread information, check for architecture 838 + * specific fallback if available 839 + */ 840 + if (is_threaded < 0) 841 + is_threaded = arch_cpu_is_threaded(); 842 + 843 + return !!is_threaded; 844 + } 845 + 846 + /* 847 + * Propagate the topology information of the processor_topology_node tree to the 848 + * cpu_topology array. 849 + */ 826 850 __weak int __init parse_acpi_topology(void) 827 851 { 852 + unsigned int max_smt_thread_num = 1; 853 + struct cpu_smt_info *entry; 854 + struct xarray hetero_cpu; 855 + unsigned long hetero_id; 856 + int cpu, topology_id; 857 + 858 + if (acpi_disabled) 859 + return 0; 860 + 861 + xa_init(&hetero_cpu); 862 + 863 + for_each_possible_cpu(cpu) { 864 + topology_id = find_acpi_cpu_topology(cpu, 0); 865 + if (topology_id < 0) 866 + return topology_id; 867 + 868 + if (acpi_cpu_is_threaded(cpu)) { 869 + cpu_topology[cpu].thread_id = topology_id; 870 + topology_id = find_acpi_cpu_topology(cpu, 1); 871 + cpu_topology[cpu].core_id = topology_id; 872 + 873 + /* 874 + * In the PPTT, CPUs below a node with the 'identical 875 + * implementation' flag have the same number of threads. 876 + * Count the number of threads for only one CPU (i.e. 877 + * one core_id) among those with the same hetero_id. 878 + * See the comment of find_acpi_cpu_topology_hetero_id() 879 + * for more details. 880 + * 881 + * One entry is created for each node having: 882 + * - the 'identical implementation' flag 883 + * - its parent not having the flag 884 + */ 885 + hetero_id = find_acpi_cpu_topology_hetero_id(cpu); 886 + entry = xa_load(&hetero_cpu, hetero_id); 887 + if (!entry) { 888 + entry = kzalloc(sizeof(*entry), GFP_KERNEL); 889 + WARN_ON_ONCE(!entry); 890 + 891 + if (entry) { 892 + entry->core_id = topology_id; 893 + entry->thread_num = 1; 894 + xa_store(&hetero_cpu, hetero_id, 895 + entry, GFP_KERNEL); 896 + } 897 + } else if (entry->core_id == topology_id) { 898 + entry->thread_num++; 899 + } 900 + } else { 901 + cpu_topology[cpu].thread_id = -1; 902 + cpu_topology[cpu].core_id = topology_id; 903 + } 904 + topology_id = find_acpi_cpu_topology_cluster(cpu); 905 + cpu_topology[cpu].cluster_id = topology_id; 906 + topology_id = find_acpi_cpu_topology_package(cpu); 907 + cpu_topology[cpu].package_id = topology_id; 908 + } 909 + 910 + /* 911 + * This is a short loop since the number of XArray elements is the 912 + * number of heterogeneous CPU clusters. On a homogeneous system 913 + * there's only one entry in the XArray. 914 + */ 915 + xa_for_each(&hetero_cpu, hetero_id, entry) { 916 + max_smt_thread_num = max(max_smt_thread_num, entry->thread_num); 917 + xa_erase(&hetero_cpu, hetero_id); 918 + kfree(entry); 919 + } 920 + 921 + cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num); 922 + xa_destroy(&hetero_cpu); 828 923 return 0; 829 924 } 830 925 831 - #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) 832 926 void __init init_cpu_topology(void) 833 927 { 834 928 int cpu, ret;
+16
drivers/base/base.h
··· 85 85 }; 86 86 #define to_driver(obj) container_of(obj, struct driver_private, kobj) 87 87 88 + #ifdef CONFIG_RUST 89 + /** 90 + * struct driver_type - Representation of a Rust driver type. 91 + */ 92 + struct driver_type { 93 + /** 94 + * @id: Representation of core::any::TypeId. 95 + */ 96 + u8 id[16]; 97 + } __packed; 98 + #endif 99 + 88 100 /** 89 101 * struct device_private - structure to hold the private to the driver core portions of the device structure. 90 102 * ··· 112 100 * @async_driver - pointer to device driver awaiting probe via async_probe 113 101 * @device - pointer back to the struct device that this structure is 114 102 * associated with. 103 + * @driver_type - The type of the bound Rust driver. 115 104 * @dead - This device is currently either in the process of or has been 116 105 * removed from the system. Any asynchronous events scheduled for this 117 106 * device should exit without taking any action. ··· 129 116 const struct device_driver *async_driver; 130 117 char *deferred_probe_reason; 131 118 struct device *device; 119 + #ifdef CONFIG_RUST 120 + struct driver_type driver_type; 121 + #endif 132 122 u8 dead:1; 133 123 }; 134 124 #define to_device_private_parent(obj) \
+1 -2
drivers/base/bus.c
··· 533 533 if (!sp) 534 534 return; 535 535 536 - if (sp->drivers_autoprobe) 537 - device_initial_probe(dev); 536 + device_initial_probe(dev); 538 537 539 538 mutex_lock(&sp->mutex); 540 539 list_for_each_entry(sif, &sp->interfaces, node)
+1 -1
drivers/base/core.c
··· 4138 4138 sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); 4139 4139 if (!sysfs_dev_char_kobj) 4140 4140 goto char_kobj_err; 4141 - device_link_wq = alloc_workqueue("device_link_wq", 0, 0); 4141 + device_link_wq = alloc_workqueue("device_link_wq", WQ_PERCPU, 0); 4142 4142 if (!device_link_wq) 4143 4143 goto wq_err; 4144 4144
+23 -5
drivers/base/cpu.c
··· 300 300 } 301 301 static DEVICE_ATTR(isolated, 0444, print_cpus_isolated, NULL); 302 302 303 - #ifdef CONFIG_NO_HZ_FULL 304 - static ssize_t print_cpus_nohz_full(struct device *dev, 305 - struct device_attribute *attr, char *buf) 303 + static ssize_t housekeeping_show(struct device *dev, 304 + struct device_attribute *attr, char *buf) 306 305 { 307 - return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask)); 306 + const struct cpumask *hk_mask; 307 + 308 + hk_mask = housekeeping_cpumask(HK_TYPE_KERNEL_NOISE); 309 + 310 + if (housekeeping_enabled(HK_TYPE_KERNEL_NOISE)) 311 + return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(hk_mask)); 312 + return sysfs_emit(buf, "\n"); 308 313 } 309 - static DEVICE_ATTR(nohz_full, 0444, print_cpus_nohz_full, NULL); 314 + static DEVICE_ATTR_RO(housekeeping); 315 + 316 + #ifdef CONFIG_NO_HZ_FULL 317 + static ssize_t nohz_full_show(struct device *dev, 318 + struct device_attribute *attr, 319 + char *buf) 320 + { 321 + if (cpumask_available(tick_nohz_full_mask)) 322 + return sysfs_emit(buf, "%*pbl\n", 323 + cpumask_pr_args(tick_nohz_full_mask)); 324 + return sysfs_emit(buf, "\n"); 325 + } 326 + static DEVICE_ATTR_RO(nohz_full); 310 327 #endif 311 328 312 329 #ifdef CONFIG_CRASH_HOTPLUG ··· 522 505 &dev_attr_offline.attr, 523 506 &dev_attr_enabled.attr, 524 507 &dev_attr_isolated.attr, 508 + &dev_attr_housekeeping.attr, 525 509 #ifdef CONFIG_NO_HZ_FULL 526 510 &dev_attr_nohz_full.attr, 527 511 #endif
+10 -2
drivers/base/dd.c
··· 193 193 * Kick the re-probe thread. It may already be scheduled, but it is 194 194 * safe to kick it again. 195 195 */ 196 - queue_work(system_unbound_wq, &deferred_probe_work); 196 + queue_work(system_dfl_wq, &deferred_probe_work); 197 197 } 198 198 199 199 /** ··· 1077 1077 1078 1078 void device_initial_probe(struct device *dev) 1079 1079 { 1080 - __device_attach(dev, true); 1080 + struct subsys_private *sp = bus_to_subsys(dev->bus); 1081 + 1082 + if (!sp) 1083 + return; 1084 + 1085 + if (sp->drivers_autoprobe) 1086 + __device_attach(dev, true); 1087 + 1088 + subsys_put(sp); 1081 1089 } 1082 1090 1083 1091 /*
-25
drivers/base/devres.c
··· 1222 1222 free_percpu(p); 1223 1223 } 1224 1224 1225 - static int devm_percpu_match(struct device *dev, void *data, void *p) 1226 - { 1227 - struct devres *devr = container_of(data, struct devres, data); 1228 - 1229 - return *(void **)devr->data == p; 1230 - } 1231 - 1232 1225 /** 1233 1226 * __devm_alloc_percpu - Resource-managed alloc_percpu 1234 1227 * @dev: Device to allocate per-cpu memory for ··· 1257 1264 return pcpu; 1258 1265 } 1259 1266 EXPORT_SYMBOL_GPL(__devm_alloc_percpu); 1260 - 1261 - /** 1262 - * devm_free_percpu - Resource-managed free_percpu 1263 - * @dev: Device this memory belongs to 1264 - * @pdata: Per-cpu memory to free 1265 - * 1266 - * Free memory allocated with devm_alloc_percpu(). 1267 - */ 1268 - void devm_free_percpu(struct device *dev, void __percpu *pdata) 1269 - { 1270 - /* 1271 - * Use devres_release() to prevent memory leakage as 1272 - * devm_free_pages() does. 1273 - */ 1274 - WARN_ON(devres_release(dev, devm_percpu_release, devm_percpu_match, 1275 - (void *)(__force unsigned long)pdata)); 1276 - } 1277 - EXPORT_SYMBOL_GPL(devm_free_percpu);
+8 -2
drivers/base/firmware_loader/sysfs.c
··· 47 47 static ssize_t timeout_store(const struct class *class, const struct class_attribute *attr, 48 48 const char *buf, size_t count) 49 49 { 50 - int tmp_loading_timeout = simple_strtol(buf, NULL, 10); 50 + int tmp_loading_timeout; 51 + 52 + if (kstrtoint(buf, 10, &tmp_loading_timeout)) 53 + return -EINVAL; 51 54 52 55 if (tmp_loading_timeout < 0) 53 56 tmp_loading_timeout = 0; ··· 160 157 struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); 161 158 struct fw_priv *fw_priv; 162 159 ssize_t written = count; 163 - int loading = simple_strtol(buf, NULL, 10); 160 + int loading; 161 + 162 + if (kstrtoint(buf, 10, &loading)) 163 + return -EINVAL; 164 164 165 165 mutex_lock(&fw_lock); 166 166 fw_priv = fw_sysfs->fw_priv;
+4 -2
drivers/base/firmware_loader/sysfs_upload.c
··· 100 100 return -EINVAL; 101 101 102 102 mutex_lock(&fwlp->lock); 103 - if (fwlp->progress == FW_UPLOAD_PROG_IDLE) 104 - ret = -ENODEV; 103 + if (fwlp->progress == FW_UPLOAD_PROG_IDLE) { 104 + mutex_unlock(&fwlp->lock); 105 + return -ENODEV; 106 + } 105 107 106 108 fwlp->ops->cancel(fwlp->fw_upload); 107 109 mutex_unlock(&fwlp->lock);
+2 -2
drivers/cpufreq/rcpufreq_dt.rs
··· 207 207 fn probe( 208 208 pdev: &platform::Device<Core>, 209 209 _id_info: Option<&Self::IdInfo>, 210 - ) -> Result<Pin<KBox<Self>>> { 210 + ) -> impl PinInit<Self, Error> { 211 211 cpufreq::Registration::<CPUFreqDTDriver>::new_foreign_owned(pdev.as_ref())?; 212 - Ok(KBox::new(Self {}, GFP_KERNEL)?.into()) 212 + Ok(Self {}) 213 213 } 214 214 } 215 215
+2 -2
drivers/gpu/drm/nova/driver.rs
··· 45 45 type IdInfo = (); 46 46 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE; 47 47 48 - fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 48 + fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 49 49 let data = try_pin_init!(NovaData { adev: adev.into() }); 50 50 51 51 let drm = drm::Device::<Self>::new(adev.as_ref(), data)?; 52 52 drm::Registration::new_foreign_owned(&drm, adev.as_ref(), 0)?; 53 53 54 - Ok(KBox::new(Self { drm }, GFP_KERNEL)?.into()) 54 + Ok(Self { drm }) 55 55 } 56 56 } 57 57
+1 -1
drivers/gpu/drm/nova/file.rs
··· 28 28 _file: &drm::File<File>, 29 29 ) -> Result<u32> { 30 30 let adev = &dev.adev; 31 - let parent = adev.parent().ok_or(ENOENT)?; 31 + let parent = adev.parent(); 32 32 let pdev: &pci::Device = parent.try_into()?; 33 33 34 34 let value = match getparam.param as u32 {
+2 -2
drivers/gpu/drm/tyr/driver.rs
··· 103 103 fn probe( 104 104 pdev: &platform::Device<Core>, 105 105 _info: Option<&Self::IdInfo>, 106 - ) -> Result<Pin<KBox<Self>>> { 106 + ) -> impl PinInit<Self, Error> { 107 107 let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?; 108 108 let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?; 109 109 let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?; ··· 143 143 let tdev: ARef<TyrDevice> = drm::Device::new(pdev.as_ref(), data)?; 144 144 drm::driver::Registration::new_foreign_owned(&tdev, pdev.as_ref(), 0)?; 145 145 146 - let driver = KBox::pin_init(try_pin_init!(TyrDriver { device: tdev }), GFP_KERNEL)?; 146 + let driver = TyrDriver { device: tdev }; 147 147 148 148 // We need this to be dev_info!() because dev_dbg!() does not work at 149 149 // all in Rust for now, and we need to see whether probe succeeded.
+22 -28
drivers/gpu/nova-core/driver.rs
··· 4 4 auxiliary, 5 5 c_str, 6 6 device::Core, 7 + devres::Devres, 7 8 dma::Device, 8 9 dma::DmaMask, 9 10 pci, ··· 24 23 pub(crate) struct NovaCore { 25 24 #[pin] 26 25 pub(crate) gpu: Gpu, 27 - _reg: auxiliary::Registration, 26 + #[pin] 27 + _reg: Devres<auxiliary::Registration>, 28 28 } 29 29 30 30 const BAR0_SIZE: usize = SZ_16M; ··· 69 67 type IdInfo = (); 70 68 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 71 69 72 - fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 73 - dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n"); 70 + fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 71 + pin_init::pin_init_scope(move || { 72 + dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n"); 74 73 75 - pdev.enable_device_mem()?; 76 - pdev.set_master(); 74 + pdev.enable_device_mem()?; 75 + pdev.set_master(); 77 76 78 - // SAFETY: No concurrent DMA allocations or mappings can be made because 79 - // the device is still being probed and therefore isn't being used by 80 - // other threads of execution. 81 - unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? }; 77 + // SAFETY: No concurrent DMA allocations or mappings can be made because 78 + // the device is still being probed and therefore isn't being used by 79 + // other threads of execution. 80 + unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? }; 82 81 83 - let devres_bar = Arc::pin_init( 84 - pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")), 85 - GFP_KERNEL, 86 - )?; 82 + let bar = Arc::pin_init( 83 + pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")), 84 + GFP_KERNEL, 85 + )?; 87 86 88 - // Used to provided a `&Bar0` to `Gpu::new` without tying it to the lifetime of 89 - // `devres_bar`. 90 - let bar_clone = Arc::clone(&devres_bar); 91 - let bar = bar_clone.access(pdev.as_ref())?; 92 - 93 - let this = KBox::pin_init( 94 - try_pin_init!(Self { 95 - gpu <- Gpu::new(pdev, devres_bar, bar), 96 - _reg: auxiliary::Registration::new( 87 + Ok(try_pin_init!(Self { 88 + gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?), 89 + _reg <- auxiliary::Registration::new( 97 90 pdev.as_ref(), 98 91 c_str!("nova-drm"), 99 92 0, // TODO[XARR]: Once it lands, use XArray; for now we don't use the ID. 100 93 crate::MODULE_NAME 101 - )?, 102 - }), 103 - GFP_KERNEL, 104 - )?; 105 - 106 - Ok(this) 94 + ), 95 + })) 96 + }) 107 97 } 108 98 109 99 fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {
+2 -2
drivers/pwm/pwm_th1520.rs
··· 337 337 fn probe( 338 338 pdev: &platform::Device<Core>, 339 339 _id_info: Option<&Self::IdInfo>, 340 - ) -> Result<Pin<KBox<Self>>> { 340 + ) -> impl PinInit<Self, Error> { 341 341 let dev = pdev.as_ref(); 342 342 let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; 343 343 ··· 374 374 375 375 pwm::Registration::register(dev, chip)?; 376 376 377 - Ok(KBox::new(Th1520PwmPlatformDriver, GFP_KERNEL)?.into()) 377 + Ok(Th1520PwmPlatformDriver) 378 378 } 379 379 } 380 380
+11 -10
fs/debugfs/inode.c
··· 35 35 static struct vfsmount *debugfs_mount; 36 36 static int debugfs_mount_count; 37 37 static bool debugfs_registered; 38 - static unsigned int debugfs_allow __ro_after_init = DEFAULT_DEBUGFS_ALLOW_BITS; 38 + static bool debugfs_enabled __ro_after_init = IS_ENABLED(CONFIG_DEBUG_FS_ALLOW_ALL); 39 39 40 40 /* 41 41 * Don't allow access attributes to be changed whilst the kernel is locked down ··· 287 287 { 288 288 int err; 289 289 290 - if (!(debugfs_allow & DEBUGFS_ALLOW_API)) 291 - return -EPERM; 292 - 293 290 err = get_tree_single(fc, debugfs_fill_super); 294 291 if (err) 295 292 return err; ··· 365 368 struct dentry *dentry; 366 369 int error; 367 370 368 - if (!(debugfs_allow & DEBUGFS_ALLOW_API)) 371 + if (!debugfs_enabled) 369 372 return ERR_PTR(-EPERM); 370 373 371 374 if (!debugfs_initialized()) ··· 880 883 { 881 884 if (str) { 882 885 if (!strcmp(str, "on")) 883 - debugfs_allow = DEBUGFS_ALLOW_API | DEBUGFS_ALLOW_MOUNT; 884 - else if (!strcmp(str, "no-mount")) 885 - debugfs_allow = DEBUGFS_ALLOW_API; 886 + debugfs_enabled = true; 886 887 else if (!strcmp(str, "off")) 887 - debugfs_allow = 0; 888 + debugfs_enabled = false; 889 + else if (!strcmp(str, "no-mount")) { 890 + pr_notice("debugfs=no-mount is a deprecated alias " 891 + "for debugfs=off\n"); 892 + debugfs_enabled = false; 893 + } 888 894 } 889 895 890 896 return 0; 891 897 } 892 898 early_param("debugfs", debugfs_kernel); 899 + 893 900 static int __init debugfs_init(void) 894 901 { 895 902 int retval; 896 903 897 - if (!(debugfs_allow & DEBUGFS_ALLOW_MOUNT)) 904 + if (!debugfs_enabled) 898 905 return -EPERM; 899 906 900 907 retval = sysfs_create_mount_point(kernel_kobj, "debug");
-13
fs/debugfs/internal.h
··· 55 55 HAS_IOCTL = 16 56 56 }; 57 57 58 - #define DEBUGFS_ALLOW_API BIT(0) 59 - #define DEBUGFS_ALLOW_MOUNT BIT(1) 60 - 61 - #ifdef CONFIG_DEBUG_FS_ALLOW_ALL 62 - #define DEFAULT_DEBUGFS_ALLOW_BITS (DEBUGFS_ALLOW_MOUNT | DEBUGFS_ALLOW_API) 63 - #endif 64 - #ifdef CONFIG_DEBUG_FS_DISALLOW_MOUNT 65 - #define DEFAULT_DEBUGFS_ALLOW_BITS (DEBUGFS_ALLOW_API) 66 - #endif 67 - #ifdef CONFIG_DEBUG_FS_ALLOW_NONE 68 - #define DEFAULT_DEBUGFS_ALLOW_BITS (0) 69 - #endif 70 - 71 58 #endif /* _DEBUGFS_INTERNAL_H_ */
+4 -1
fs/kernfs/dir.c
··· 675 675 if (parent) { 676 676 ret = security_kernfs_init_security(parent, kn); 677 677 if (ret) 678 - goto err_out3; 678 + goto err_out4; 679 679 } 680 680 681 681 return kn; 682 682 683 + err_out4: 684 + simple_xattrs_free(&kn->iattr->xattrs, NULL); 685 + kmem_cache_free(kernfs_iattrs_cache, kn->iattr); 683 686 err_out3: 684 687 spin_lock(&root->kernfs_idr_lock); 685 688 idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
+1
fs/kernfs/mount.c
··· 298 298 if (info->root->flags & KERNFS_ROOT_SUPPORT_EXPORTOP) 299 299 sb->s_export_op = &kernfs_export_ops; 300 300 sb->s_time_gran = 1; 301 + sb->s_maxbytes = MAX_LFS_FILESIZE; 301 302 302 303 /* sysfs dentries and inodes don't require IO to create */ 303 304 sb->s_shrink->seeks = 0;
+8 -2
fs/sysfs/group.c
··· 36 36 if (grp->attrs && grp->attrs[0] && grp->is_visible) 37 37 return grp->is_visible(kobj, grp->attrs[0], 0); 38 38 39 + if (grp->attrs && grp->attrs[0] && grp->is_visible_const) 40 + return grp->is_visible_const(kobj, grp->attrs[0], 0); 41 + 39 42 if (grp->bin_attrs && grp->bin_attrs[0] && grp->is_bin_visible) 40 43 return grp->is_bin_visible(kobj, grp->bin_attrs[0], 0); 41 44 ··· 64 61 */ 65 62 if (update) 66 63 kernfs_remove_by_name(parent, (*attr)->name); 67 - if (grp->is_visible) { 68 - mode = grp->is_visible(kobj, *attr, i); 64 + if (grp->is_visible || grp->is_visible_const) { 65 + if (grp->is_visible) 66 + mode = grp->is_visible(kobj, *attr, i); 67 + else 68 + mode = grp->is_visible_const(kobj, *attr, i); 69 69 mode &= ~SYSFS_GROUP_INVISIBLE; 70 70 if (!mode) 71 71 continue;
+5
include/linux/arch_topology.h
··· 80 80 #define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) 81 81 #define topology_cluster_cpumask(cpu) (&cpu_topology[cpu].cluster_sibling) 82 82 #define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) 83 + 84 + #ifndef arch_cpu_is_threaded 85 + #define arch_cpu_is_threaded() (0) 86 + #endif 87 + 83 88 void init_cpu_topology(void); 84 89 void store_cpu_topology(unsigned int cpuid); 85 90 const struct cpumask *cpu_coregroup_mask(int cpu);
-19
include/linux/device.h
··· 281 281 void device_remove_bin_file(struct device *dev, 282 282 const struct bin_attribute *attr); 283 283 284 - /** 285 - * devm_alloc_percpu - Resource-managed alloc_percpu 286 - * @dev: Device to allocate per-cpu memory for 287 - * @type: Type to allocate per-cpu memory for 288 - * 289 - * Managed alloc_percpu. Per-cpu memory allocated with this function is 290 - * automatically freed on driver detach. 291 - * 292 - * RETURNS: 293 - * Pointer to allocated memory on success, NULL on failure. 294 - */ 295 - #define devm_alloc_percpu(dev, type) \ 296 - ((typeof(type) __percpu *)__devm_alloc_percpu((dev), sizeof(type), \ 297 - __alignof__(type))) 298 - 299 - void __percpu *__devm_alloc_percpu(struct device *dev, size_t size, 300 - size_t align); 301 - void devm_free_percpu(struct device *dev, void __percpu *pdata); 302 - 303 284 struct device_dma_parameters { 304 285 /* 305 286 * a low level driver may set these to teach IOMMU code about
+17
include/linux/device/devres.h
··· 9 9 #include <linux/stdarg.h> 10 10 #include <linux/types.h> 11 11 #include <asm/bug.h> 12 + #include <asm/percpu.h> 12 13 13 14 struct device; 14 15 struct device_node; ··· 96 95 devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, va_list ap); 97 96 char * __printf(3, 4) __malloc 98 97 devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...); 98 + 99 + /** 100 + * devm_alloc_percpu - Resource-managed alloc_percpu 101 + * @dev: Device to allocate per-cpu memory for 102 + * @type: Type to allocate per-cpu memory for 103 + * 104 + * Managed alloc_percpu. Per-cpu memory allocated with this function is 105 + * automatically freed on driver detach. 106 + * 107 + * RETURNS: 108 + * Pointer to allocated memory on success, NULL on failure. 109 + */ 110 + #define devm_alloc_percpu(dev, type) \ 111 + ((typeof(type) __percpu *)__devm_alloc_percpu((dev), sizeof(type), __alignof__(type))) 112 + 113 + void __percpu *__devm_alloc_percpu(struct device *dev, size_t size, size_t align); 99 114 100 115 unsigned long devm_get_free_pages(struct device *dev, gfp_t gfp_mask, unsigned int order); 101 116 void devm_free_pages(struct device *dev, unsigned long addr);
+1 -1
include/linux/mod_devicetable.h
··· 867 867 kernel_ulong_t driver_data; 868 868 }; 869 869 870 - #define AUXILIARY_NAME_SIZE 32 870 + #define AUXILIARY_NAME_SIZE 40 871 871 #define AUXILIARY_MODULE_PREFIX "auxiliary:" 872 872 873 873 struct auxiliary_device_id {
+3 -3
include/linux/platform_device.h
··· 80 80 devm_platform_get_and_ioremap_resource(struct platform_device *pdev, 81 81 unsigned int index, struct resource **res) 82 82 { 83 - return ERR_PTR(-EINVAL); 83 + return IOMEM_ERR_PTR(-EINVAL); 84 84 } 85 85 86 86 ··· 88 88 devm_platform_ioremap_resource(struct platform_device *pdev, 89 89 unsigned int index) 90 90 { 91 - return ERR_PTR(-EINVAL); 91 + return IOMEM_ERR_PTR(-EINVAL); 92 92 } 93 93 94 94 static inline void __iomem * 95 95 devm_platform_ioremap_resource_byname(struct platform_device *pdev, 96 96 const char *name) 97 97 { 98 - return ERR_PTR(-EINVAL); 98 + return IOMEM_ERR_PTR(-EINVAL); 99 99 } 100 100 101 101 #endif
+29 -19
include/linux/sysfs.h
··· 58 58 #define sysfs_attr_init(attr) do {} while (0) 59 59 #endif 60 60 61 + #ifdef CONFIG_CFI 62 + #define __SYSFS_FUNCTION_ALTERNATIVE(MEMBERS...) struct { MEMBERS } 63 + #else 64 + #define __SYSFS_FUNCTION_ALTERNATIVE(MEMBERS...) union { MEMBERS } 65 + #endif 66 + 61 67 /** 62 68 * struct attribute_group - data structure used to declare an attribute group. 63 69 * @name: Optional: Attribute group name ··· 104 98 */ 105 99 struct attribute_group { 106 100 const char *name; 107 - umode_t (*is_visible)(struct kobject *, 108 - struct attribute *, int); 101 + __SYSFS_FUNCTION_ALTERNATIVE( 102 + umode_t (*is_visible)(struct kobject *, 103 + struct attribute *, int); 104 + umode_t (*is_visible_const)(struct kobject *, 105 + const struct attribute *, int); 106 + ); 109 107 umode_t (*is_bin_visible)(struct kobject *, 110 108 const struct bin_attribute *, int); 111 109 size_t (*bin_size)(struct kobject *, 112 110 const struct bin_attribute *, 113 111 int); 114 - struct attribute **attrs; 112 + union { 113 + struct attribute **attrs; 114 + const struct attribute *const *attrs_const; 115 + }; 115 116 const struct bin_attribute *const *bin_attrs; 116 117 }; 117 118 ··· 251 238 .store = _store, \ 252 239 } 253 240 254 - #define __ATTR_RO(_name) { \ 255 - .attr = { .name = __stringify(_name), .mode = 0444 }, \ 256 - .show = _name##_show, \ 257 - } 258 - 259 241 #define __ATTR_RO_MODE(_name, _mode) { \ 260 242 .attr = { .name = __stringify(_name), \ 261 243 .mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \ 262 244 .show = _name##_show, \ 263 245 } 264 246 265 - #define __ATTR_RW_MODE(_name, _mode) { \ 266 - .attr = { .name = __stringify(_name), \ 267 - .mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \ 268 - .show = _name##_show, \ 269 - .store = _name##_store, \ 270 - } 247 + #define __ATTR_RO(_name) \ 248 + __ATTR_RO_MODE(_name, 0444) 271 249 272 - #define __ATTR_WO(_name) { \ 273 - .attr = { .name = __stringify(_name), .mode = 0200 }, \ 274 - .store = _name##_store, \ 275 - } 250 + #define __ATTR_RW_MODE(_name, _mode) \ 251 + __ATTR(_name, _mode, _name##_show, _name##_store) 252 + 253 + #define __ATTR_WO(_name) \ 254 + __ATTR(_name, 0200, NULL, _name##_store) 276 255 277 256 #define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store) 278 257 ··· 289 284 290 285 #define ATTRIBUTE_GROUPS(_name) \ 291 286 static const struct attribute_group _name##_group = { \ 292 - .attrs = _name##_attrs, \ 287 + .attrs = _Generic(_name##_attrs, \ 288 + struct attribute **: \ 289 + _name##_attrs, \ 290 + const struct attribute *const *: \ 291 + (void *)_name##_attrs \ 292 + ), \ 293 293 }; \ 294 294 __ATTRIBUTE_GROUPS(_name) 295 295
+1 -8
lib/Kconfig.debug
··· 688 688 help 689 689 This selects the default access restrictions for debugfs. 690 690 It can be overridden with kernel command line option 691 - debugfs=[on,no-mount,off]. The restrictions apply for API access 691 + debugfs=[on,off]. The restrictions apply for API access 692 692 and filesystem registration. 693 693 694 694 config DEBUG_FS_ALLOW_ALL ··· 696 696 help 697 697 No restrictions apply. Both API and filesystem registration 698 698 is on. This is the normal default operation. 699 - 700 - config DEBUG_FS_DISALLOW_MOUNT 701 - bool "Do not register debugfs as filesystem" 702 - help 703 - The API is open but filesystem is not loaded. Clients can still do 704 - their work and read with debug tools that do not need 705 - debugfs filesystem. 706 699 707 700 config DEBUG_FS_ALLOW_NONE 708 701 bool "No access"
+7
rust/bindings/bindings_helper.h
··· 58 58 #include <linux/firmware.h> 59 59 #include <linux/interrupt.h> 60 60 #include <linux/fs.h> 61 + #include <linux/i2c.h> 61 62 #include <linux/ioport.h> 62 63 #include <linux/jiffies.h> 63 64 #include <linux/jump_label.h> ··· 86 85 #include <linux/workqueue.h> 87 86 #include <linux/xarray.h> 88 87 #include <trace/events/rust_sample.h> 88 + 89 + /* 90 + * The driver-core Rust code needs to know about some C driver-core private 91 + * structures. 92 + */ 93 + #include <../../drivers/base/base.h> 89 94 90 95 #if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE) 91 96 // Used by `#[export]` in `drivers/gpu/drm/drm_panic_qr.rs`.
+13 -1
rust/helpers/pci.c
··· 23 23 } 24 24 25 25 #ifndef CONFIG_PCI_MSI 26 + int rust_helper_pci_alloc_irq_vectors(struct pci_dev *dev, 27 + unsigned int min_vecs, 28 + unsigned int max_vecs, 29 + unsigned int flags) 30 + { 31 + return pci_alloc_irq_vectors(dev, min_vecs, max_vecs, flags); 32 + } 33 + 34 + void rust_helper_pci_free_irq_vectors(struct pci_dev *dev) 35 + { 36 + pci_free_irq_vectors(dev); 37 + } 38 + 26 39 int rust_helper_pci_irq_vector(struct pci_dev *pdev, unsigned int nvec) 27 40 { 28 41 return pci_irq_vector(pdev, nvec); 29 42 } 30 - 31 43 #endif
+5
rust/helpers/time.c
··· 33 33 { 34 34 return ktime_to_ms(kt); 35 35 } 36 + 37 + void rust_helper_udelay(unsigned long usec) 38 + { 39 + udelay(usec); 40 + }
+72 -42
rust/kernel/auxiliary.rs
··· 7 7 use crate::{ 8 8 bindings, container_of, device, 9 9 device_id::{RawDeviceId, RawDeviceIdIndex}, 10 + devres::Devres, 10 11 driver, 11 12 error::{from_result, to_result, Result}, 12 13 prelude::*, ··· 16 15 }; 17 16 use core::{ 18 17 marker::PhantomData, 18 + mem::offset_of, 19 19 ptr::{addr_of_mut, NonNull}, 20 20 }; 21 21 ··· 70 68 let info = T::ID_TABLE.info(id.index()); 71 69 72 70 from_result(|| { 73 - let data = T::probe(adev, info)?; 71 + let data = T::probe(adev, info); 74 72 75 - adev.as_ref().set_drvdata(data); 73 + adev.as_ref().set_drvdata(data)?; 76 74 Ok(0) 77 75 }) 78 76 } ··· 87 85 // SAFETY: `remove_callback` is only ever called after a successful call to 88 86 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 89 87 // and stored a `Pin<KBox<T>>`. 90 - drop(unsafe { adev.as_ref().drvdata_obtain::<Pin<KBox<T>>>() }); 88 + drop(unsafe { adev.as_ref().drvdata_obtain::<T>() }); 91 89 } 92 90 } 93 91 ··· 186 184 /// Auxiliary driver probe. 187 185 /// 188 186 /// Called when an auxiliary device is matches a corresponding driver. 189 - fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 187 + fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>; 190 188 } 191 189 192 190 /// The auxiliary device representation. ··· 216 214 // `struct auxiliary_device`. 217 215 unsafe { (*self.as_raw()).id } 218 216 } 217 + } 219 218 220 - /// Returns a reference to the parent [`device::Device`], if any. 221 - pub fn parent(&self) -> Option<&device::Device> { 222 - self.as_ref().parent() 219 + impl Device<device::Bound> { 220 + /// Returns a bound reference to the parent [`device::Device`]. 221 + pub fn parent(&self) -> &device::Device<device::Bound> { 222 + let parent = (**self).parent(); 223 + 224 + // SAFETY: A bound auxiliary device always has a bound parent device. 225 + unsafe { parent.as_bound() } 223 226 } 224 227 } 225 228 226 229 impl Device { 230 + /// Returns a reference to the parent [`device::Device`]. 231 + pub fn parent(&self) -> &device::Device { 232 + // SAFETY: A `struct auxiliary_device` always has a parent. 233 + unsafe { self.as_ref().parent().unwrap_unchecked() } 234 + } 235 + 227 236 extern "C" fn release(dev: *mut bindings::device) { 228 237 // SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device` 229 238 // embedded in `struct auxiliary_device`. ··· 244 231 // `KBox::new(Opaque::<bindings::auxiliary_device>::zeroed(), GFP_KERNEL)`. 245 232 let _ = unsafe { KBox::<Opaque<bindings::auxiliary_device>>::from_raw(adev.cast()) }; 246 233 } 234 + } 235 + 236 + // SAFETY: `auxiliary::Device` is a transparent wrapper of `struct auxiliary_device`. 237 + // The offset is guaranteed to point to a valid device field inside `auxiliary::Device`. 238 + unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx> { 239 + const OFFSET: usize = offset_of!(bindings::auxiliary_device, dev); 247 240 } 248 241 249 242 // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic ··· 297 278 298 279 /// The registration of an auxiliary device. 299 280 /// 300 - /// This type represents the registration of a [`struct auxiliary_device`]. When an instance of this 301 - /// type is dropped, its respective auxiliary device will be unregistered from the system. 281 + /// This type represents the registration of a [`struct auxiliary_device`]. When its parent device 282 + /// is unbound, the corresponding auxiliary device will be unregistered from the system. 302 283 /// 303 284 /// # Invariants 304 285 /// ··· 308 289 309 290 impl Registration { 310 291 /// Create and register a new auxiliary device. 311 - pub fn new(parent: &device::Device, name: &CStr, id: u32, modname: &CStr) -> Result<Self> { 312 - let boxed = KBox::new(Opaque::<bindings::auxiliary_device>::zeroed(), GFP_KERNEL)?; 313 - let adev = boxed.get(); 292 + pub fn new<'a>( 293 + parent: &'a device::Device<device::Bound>, 294 + name: &'a CStr, 295 + id: u32, 296 + modname: &'a CStr, 297 + ) -> impl PinInit<Devres<Self>, Error> + 'a { 298 + pin_init::pin_init_scope(move || { 299 + let boxed = KBox::new(Opaque::<bindings::auxiliary_device>::zeroed(), GFP_KERNEL)?; 300 + let adev = boxed.get(); 314 301 315 - // SAFETY: It's safe to set the fields of `struct auxiliary_device` on initialization. 316 - unsafe { 317 - (*adev).dev.parent = parent.as_raw(); 318 - (*adev).dev.release = Some(Device::release); 319 - (*adev).name = name.as_char_ptr(); 320 - (*adev).id = id; 321 - } 302 + // SAFETY: It's safe to set the fields of `struct auxiliary_device` on initialization. 303 + unsafe { 304 + (*adev).dev.parent = parent.as_raw(); 305 + (*adev).dev.release = Some(Device::release); 306 + (*adev).name = name.as_char_ptr(); 307 + (*adev).id = id; 308 + } 322 309 323 - // SAFETY: `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`, 324 - // which has not been initialized yet. 325 - unsafe { bindings::auxiliary_device_init(adev) }; 326 - 327 - // Now that `adev` is initialized, leak the `Box`; the corresponding memory will be freed 328 - // by `Device::release` when the last reference to the `struct auxiliary_device` is dropped. 329 - let _ = KBox::into_raw(boxed); 330 - 331 - // SAFETY: 332 - // - `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`, which has 333 - // been initialialized, 334 - // - `modname.as_char_ptr()` is a NULL terminated string. 335 - let ret = unsafe { bindings::__auxiliary_device_add(adev, modname.as_char_ptr()) }; 336 - if ret != 0 { 337 310 // SAFETY: `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`, 338 - // which has been initialialized. 339 - unsafe { bindings::auxiliary_device_uninit(adev) }; 311 + // which has not been initialized yet. 312 + unsafe { bindings::auxiliary_device_init(adev) }; 340 313 341 - return Err(Error::from_errno(ret)); 342 - } 314 + // Now that `adev` is initialized, leak the `Box`; the corresponding memory will be 315 + // freed by `Device::release` when the last reference to the `struct auxiliary_device` 316 + // is dropped. 317 + let _ = KBox::into_raw(boxed); 343 318 344 - // SAFETY: `adev` is guaranteed to be non-null, since the `KBox` was allocated successfully. 345 - // 346 - // INVARIANT: The device will remain registered until `auxiliary_device_delete()` is called, 347 - // which happens in `Self::drop()`. 348 - Ok(Self(unsafe { NonNull::new_unchecked(adev) })) 319 + // SAFETY: 320 + // - `adev` is guaranteed to be a valid pointer to a `struct auxiliary_device`, which 321 + // has been initialized, 322 + // - `modname.as_char_ptr()` is a NULL terminated string. 323 + let ret = unsafe { bindings::__auxiliary_device_add(adev, modname.as_char_ptr()) }; 324 + if ret != 0 { 325 + // SAFETY: `adev` is guaranteed to be a valid pointer to a 326 + // `struct auxiliary_device`, which has been initialized. 327 + unsafe { bindings::auxiliary_device_uninit(adev) }; 328 + 329 + return Err(Error::from_errno(ret)); 330 + } 331 + 332 + // INVARIANT: The device will remain registered until `auxiliary_device_delete()` is 333 + // called, which happens in `Self::drop()`. 334 + Ok(Devres::new( 335 + parent, 336 + // SAFETY: `adev` is guaranteed to be non-null, since the `KBox` was allocated 337 + // successfully. 338 + Self(unsafe { NonNull::new_unchecked(adev) }), 339 + )) 340 + }) 349 341 } 350 342 } 351 343
+2 -2
rust/kernel/cpufreq.rs
··· 893 893 /// fn probe( 894 894 /// pdev: &platform::Device<Core>, 895 895 /// _id_info: Option<&Self::IdInfo>, 896 - /// ) -> Result<Pin<KBox<Self>>> { 896 + /// ) -> impl PinInit<Self, Error> { 897 897 /// cpufreq::Registration::<SampleDriver>::new_foreign_owned(pdev.as_ref())?; 898 - /// Ok(KBox::new(Self {}, GFP_KERNEL)?.into()) 898 + /// Ok(Self {}) 899 899 /// } 900 900 /// } 901 901 /// ```
+108 -2
rust/kernel/debugfs.rs
··· 21 21 use core::ops::Deref; 22 22 23 23 mod traits; 24 - pub use traits::{Reader, Writer}; 24 + pub use traits::{BinaryReader, BinaryReaderMut, BinaryWriter, Reader, Writer}; 25 25 26 26 mod callback_adapters; 27 27 use callback_adapters::{FormatAdapter, NoWriter, WritableAdapter}; 28 28 mod file_ops; 29 - use file_ops::{FileOps, ReadFile, ReadWriteFile, WriteFile}; 29 + use file_ops::{ 30 + BinaryReadFile, BinaryReadWriteFile, BinaryWriteFile, FileOps, ReadFile, ReadWriteFile, 31 + WriteFile, 32 + }; 30 33 #[cfg(CONFIG_DEBUG_FS)] 31 34 mod entry; 32 35 #[cfg(CONFIG_DEBUG_FS)] ··· 153 150 self.create_file(name, data, file_ops) 154 151 } 155 152 153 + /// Creates a read-only binary file in this directory. 154 + /// 155 + /// The file's contents are produced by invoking [`BinaryWriter::write_to_slice`] on the value 156 + /// initialized by `data`. 157 + /// 158 + /// # Examples 159 + /// 160 + /// ``` 161 + /// # use kernel::c_str; 162 + /// # use kernel::debugfs::Dir; 163 + /// # use kernel::prelude::*; 164 + /// # let dir = Dir::new(c_str!("my_debugfs_dir")); 165 + /// let file = KBox::pin_init(dir.read_binary_file(c_str!("foo"), [0x1, 0x2]), GFP_KERNEL)?; 166 + /// # Ok::<(), Error>(()) 167 + /// ``` 168 + pub fn read_binary_file<'a, T, E: 'a>( 169 + &'a self, 170 + name: &'a CStr, 171 + data: impl PinInit<T, E> + 'a, 172 + ) -> impl PinInit<File<T>, E> + 'a 173 + where 174 + T: BinaryWriter + Send + Sync + 'static, 175 + { 176 + self.create_file(name, data, &T::FILE_OPS) 177 + } 178 + 156 179 /// Creates a read-only file in this directory, with contents from a callback. 157 180 /// 158 181 /// `f` must be a function item or a non-capturing closure. ··· 235 206 self.create_file(name, data, file_ops) 236 207 } 237 208 209 + /// Creates a read-write binary file in this directory. 210 + /// 211 + /// Reading the file uses the [`BinaryWriter`] implementation. 212 + /// Writing to the file uses the [`BinaryReader`] implementation. 213 + pub fn read_write_binary_file<'a, T, E: 'a>( 214 + &'a self, 215 + name: &'a CStr, 216 + data: impl PinInit<T, E> + 'a, 217 + ) -> impl PinInit<File<T>, E> + 'a 218 + where 219 + T: BinaryWriter + BinaryReader + Send + Sync + 'static, 220 + { 221 + let file_ops = &<T as BinaryReadWriteFile<_>>::FILE_OPS; 222 + self.create_file(name, data, file_ops) 223 + } 224 + 238 225 /// Creates a read-write file in this directory, with logic from callbacks. 239 226 /// 240 227 /// Reading from the file is handled by `f`. Writing to the file is handled by `w`. ··· 289 244 ) -> impl PinInit<File<T>, E> + 'a 290 245 where 291 246 T: Reader + Send + Sync + 'static, 247 + { 248 + self.create_file(name, data, &T::FILE_OPS) 249 + } 250 + 251 + /// Creates a write-only binary file in this directory. 252 + /// 253 + /// The file owns its backing data. Writing to the file uses the [`BinaryReader`] 254 + /// implementation. 255 + /// 256 + /// The file is removed when the returned [`File`] is dropped. 257 + pub fn write_binary_file<'a, T, E: 'a>( 258 + &'a self, 259 + name: &'a CStr, 260 + data: impl PinInit<T, E> + 'a, 261 + ) -> impl PinInit<File<T>, E> + 'a 262 + where 263 + T: BinaryReader + Send + Sync + 'static, 292 264 { 293 265 self.create_file(name, data, &T::FILE_OPS) 294 266 } ··· 530 468 self.create_file(name, data, &T::FILE_OPS) 531 469 } 532 470 471 + /// Creates a read-only binary file in this directory. 472 + /// 473 + /// The file's contents are produced by invoking [`BinaryWriter::write_to_slice`]. 474 + /// 475 + /// This function does not produce an owning handle to the file. The created file is removed 476 + /// when the [`Scope`] that this directory belongs to is dropped. 477 + pub fn read_binary_file<T: BinaryWriter + Send + Sync + 'static>( 478 + &self, 479 + name: &CStr, 480 + data: &'data T, 481 + ) { 482 + self.create_file(name, data, &T::FILE_OPS) 483 + } 484 + 533 485 /// Creates a read-only file in this directory, with contents from a callback. 534 486 /// 535 487 /// The file contents are generated by calling `f` with `data`. ··· 578 502 data: &'data T, 579 503 ) { 580 504 let vtable = &<T as ReadWriteFile<_>>::FILE_OPS; 505 + self.create_file(name, data, vtable) 506 + } 507 + 508 + /// Creates a read-write binary file in this directory. 509 + /// 510 + /// Reading the file uses the [`BinaryWriter`] implementation on `data`. Writing to the file 511 + /// uses the [`BinaryReader`] implementation on `data`. 512 + /// 513 + /// This function does not produce an owning handle to the file. The created file is removed 514 + /// when the [`Scope`] that this directory belongs to is dropped. 515 + pub fn read_write_binary_file<T: BinaryWriter + BinaryReader + Send + Sync + 'static>( 516 + &self, 517 + name: &CStr, 518 + data: &'data T, 519 + ) { 520 + let vtable = &<T as BinaryReadWriteFile<_>>::FILE_OPS; 581 521 self.create_file(name, data, vtable) 582 522 } 583 523 ··· 634 542 pub fn write_only_file<T: Reader + Send + Sync + 'static>(&self, name: &CStr, data: &'data T) { 635 543 let vtable = &<T as WriteFile<_>>::FILE_OPS; 636 544 self.create_file(name, data, vtable) 545 + } 546 + 547 + /// Creates a write-only binary file in this directory. 548 + /// 549 + /// Writing to the file uses the [`BinaryReader`] implementation on `data`. 550 + /// 551 + /// This function does not produce an owning handle to the file. The created file is removed 552 + /// when the [`Scope`] that this directory belongs to is dropped. 553 + pub fn write_binary_file<T: BinaryReader + Send + Sync + 'static>( 554 + &self, 555 + name: &CStr, 556 + data: &'data T, 557 + ) { 558 + self.create_file(name, data, &T::FILE_OPS) 637 559 } 638 560 639 561 /// Creates a write-only file in this directory, with write logic from a callback.
+139 -1
rust/kernel/debugfs/file_ops.rs
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 // Copyright (C) 2025 Google LLC. 3 3 4 - use super::{Reader, Writer}; 4 + use super::{BinaryReader, BinaryWriter, Reader, Writer}; 5 5 use crate::debugfs::callback_adapters::Adapter; 6 6 use crate::fmt; 7 + use crate::fs::file; 7 8 use crate::prelude::*; 8 9 use crate::seq_file::SeqFile; 9 10 use crate::seq_print; ··· 244 243 // a `T` and be legal to convert to a shared reference, which `write_only_open` 245 244 // satisfies. 246 245 unsafe { FileOps::new(operations, 0o200) } 246 + }; 247 + } 248 + 249 + extern "C" fn blob_read<T: BinaryWriter>( 250 + file: *mut bindings::file, 251 + buf: *mut c_char, 252 + count: usize, 253 + ppos: *mut bindings::loff_t, 254 + ) -> isize { 255 + // SAFETY: 256 + // - `file` is a valid pointer to a `struct file`. 257 + // - The type invariant of `FileOps` guarantees that `private_data` points to a valid `T`. 258 + let this = unsafe { &*((*file).private_data.cast::<T>()) }; 259 + 260 + // SAFETY: 261 + // - `ppos` is a valid `file::Offset` pointer. 262 + // - We have exclusive access to `ppos`. 263 + let pos: &mut file::Offset = unsafe { &mut *ppos }; 264 + 265 + let mut writer = UserSlice::new(UserPtr::from_ptr(buf.cast()), count).writer(); 266 + 267 + let ret = || -> Result<isize> { 268 + let written = this.write_to_slice(&mut writer, pos)?; 269 + 270 + Ok(written.try_into()?) 271 + }(); 272 + 273 + match ret { 274 + Ok(n) => n, 275 + Err(e) => e.to_errno() as isize, 276 + } 277 + } 278 + 279 + /// Representation of [`FileOps`] for read only binary files. 280 + pub(crate) trait BinaryReadFile<T> { 281 + const FILE_OPS: FileOps<T>; 282 + } 283 + 284 + impl<T: BinaryWriter + Sync> BinaryReadFile<T> for T { 285 + const FILE_OPS: FileOps<T> = { 286 + let operations = bindings::file_operations { 287 + read: Some(blob_read::<T>), 288 + llseek: Some(bindings::default_llseek), 289 + open: Some(bindings::simple_open), 290 + // SAFETY: `file_operations` supports zeroes in all fields. 291 + ..unsafe { core::mem::zeroed() } 292 + }; 293 + 294 + // SAFETY: 295 + // - The private data of `struct inode` does always contain a pointer to a valid `T`. 296 + // - `simple_open()` stores the `struct inode`'s private data in the private data of the 297 + // corresponding `struct file`. 298 + // - `blob_read()` re-creates a reference to `T` from the `struct file`'s private data. 299 + // - `default_llseek()` does not access the `struct file`'s private data. 300 + unsafe { FileOps::new(operations, 0o400) } 301 + }; 302 + } 303 + 304 + extern "C" fn blob_write<T: BinaryReader>( 305 + file: *mut bindings::file, 306 + buf: *const c_char, 307 + count: usize, 308 + ppos: *mut bindings::loff_t, 309 + ) -> isize { 310 + // SAFETY: 311 + // - `file` is a valid pointer to a `struct file`. 312 + // - The type invariant of `FileOps` guarantees that `private_data` points to a valid `T`. 313 + let this = unsafe { &*((*file).private_data.cast::<T>()) }; 314 + 315 + // SAFETY: 316 + // - `ppos` is a valid `file::Offset` pointer. 317 + // - We have exclusive access to `ppos`. 318 + let pos: &mut file::Offset = unsafe { &mut *ppos }; 319 + 320 + let mut reader = UserSlice::new(UserPtr::from_ptr(buf.cast_mut().cast()), count).reader(); 321 + 322 + let ret = || -> Result<isize> { 323 + let read = this.read_from_slice(&mut reader, pos)?; 324 + 325 + Ok(read.try_into()?) 326 + }(); 327 + 328 + match ret { 329 + Ok(n) => n, 330 + Err(e) => e.to_errno() as isize, 331 + } 332 + } 333 + 334 + /// Representation of [`FileOps`] for write only binary files. 335 + pub(crate) trait BinaryWriteFile<T> { 336 + const FILE_OPS: FileOps<T>; 337 + } 338 + 339 + impl<T: BinaryReader + Sync> BinaryWriteFile<T> for T { 340 + const FILE_OPS: FileOps<T> = { 341 + let operations = bindings::file_operations { 342 + write: Some(blob_write::<T>), 343 + llseek: Some(bindings::default_llseek), 344 + open: Some(bindings::simple_open), 345 + // SAFETY: `file_operations` supports zeroes in all fields. 346 + ..unsafe { core::mem::zeroed() } 347 + }; 348 + 349 + // SAFETY: 350 + // - The private data of `struct inode` does always contain a pointer to a valid `T`. 351 + // - `simple_open()` stores the `struct inode`'s private data in the private data of the 352 + // corresponding `struct file`. 353 + // - `blob_write()` re-creates a reference to `T` from the `struct file`'s private data. 354 + // - `default_llseek()` does not access the `struct file`'s private data. 355 + unsafe { FileOps::new(operations, 0o200) } 356 + }; 357 + } 358 + 359 + /// Representation of [`FileOps`] for read/write binary files. 360 + pub(crate) trait BinaryReadWriteFile<T> { 361 + const FILE_OPS: FileOps<T>; 362 + } 363 + 364 + impl<T: BinaryWriter + BinaryReader + Sync> BinaryReadWriteFile<T> for T { 365 + const FILE_OPS: FileOps<T> = { 366 + let operations = bindings::file_operations { 367 + read: Some(blob_read::<T>), 368 + write: Some(blob_write::<T>), 369 + llseek: Some(bindings::default_llseek), 370 + open: Some(bindings::simple_open), 371 + // SAFETY: `file_operations` supports zeroes in all fields. 372 + ..unsafe { core::mem::zeroed() } 373 + }; 374 + 375 + // SAFETY: 376 + // - The private data of `struct inode` does always contain a pointer to a valid `T`. 377 + // - `simple_open()` stores the `struct inode`'s private data in the private data of the 378 + // corresponding `struct file`. 379 + // - `blob_read()` re-creates a reference to `T` from the `struct file`'s private data. 380 + // - `blob_write()` re-creates a reference to `T` from the `struct file`'s private data. 381 + // - `default_llseek()` does not access the `struct file`'s private data. 382 + unsafe { FileOps::new(operations, 0o600) } 247 383 }; 248 384 }
+237 -1
rust/kernel/debugfs/traits.rs
··· 3 3 4 4 //! Traits for rendering or updating values exported to DebugFS. 5 5 6 + use crate::alloc::Allocator; 6 7 use crate::fmt; 8 + use crate::fs::file; 7 9 use crate::prelude::*; 8 10 use crate::sync::atomic::{Atomic, AtomicBasicOps, AtomicType, Relaxed}; 11 + use crate::sync::Arc; 9 12 use crate::sync::Mutex; 10 - use crate::uaccess::UserSliceReader; 13 + use crate::transmute::{AsBytes, FromBytes}; 14 + use crate::uaccess::{UserSliceReader, UserSliceWriter}; 15 + use core::ops::{Deref, DerefMut}; 11 16 use core::str::FromStr; 12 17 13 18 /// A trait for types that can be written into a string. ··· 38 33 impl<T: fmt::Debug> Writer for T { 39 34 fn write(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 40 35 writeln!(f, "{self:?}") 36 + } 37 + } 38 + 39 + /// Trait for types that can be written out as binary. 40 + pub trait BinaryWriter { 41 + /// Writes the binary form of `self` into `writer`. 42 + /// 43 + /// `offset` is the requested offset into the binary representation of `self`. 44 + /// 45 + /// On success, returns the number of bytes written in to `writer`. 46 + fn write_to_slice( 47 + &self, 48 + writer: &mut UserSliceWriter, 49 + offset: &mut file::Offset, 50 + ) -> Result<usize>; 51 + } 52 + 53 + // Base implementation for any `T: AsBytes`. 54 + impl<T: AsBytes> BinaryWriter for T { 55 + fn write_to_slice( 56 + &self, 57 + writer: &mut UserSliceWriter, 58 + offset: &mut file::Offset, 59 + ) -> Result<usize> { 60 + writer.write_slice_file(self.as_bytes(), offset) 61 + } 62 + } 63 + 64 + // Delegate for `Mutex<T>`: Support a `T` with an outer mutex. 65 + impl<T: BinaryWriter> BinaryWriter for Mutex<T> { 66 + fn write_to_slice( 67 + &self, 68 + writer: &mut UserSliceWriter, 69 + offset: &mut file::Offset, 70 + ) -> Result<usize> { 71 + let guard = self.lock(); 72 + 73 + guard.write_to_slice(writer, offset) 74 + } 75 + } 76 + 77 + // Delegate for `Box<T, A>`: Support a `Box<T, A>` with no lock or an inner lock. 78 + impl<T, A> BinaryWriter for Box<T, A> 79 + where 80 + T: BinaryWriter, 81 + A: Allocator, 82 + { 83 + fn write_to_slice( 84 + &self, 85 + writer: &mut UserSliceWriter, 86 + offset: &mut file::Offset, 87 + ) -> Result<usize> { 88 + self.deref().write_to_slice(writer, offset) 89 + } 90 + } 91 + 92 + // Delegate for `Pin<Box<T, A>>`: Support a `Pin<Box<T, A>>` with no lock or an inner lock. 93 + impl<T, A> BinaryWriter for Pin<Box<T, A>> 94 + where 95 + T: BinaryWriter, 96 + A: Allocator, 97 + { 98 + fn write_to_slice( 99 + &self, 100 + writer: &mut UserSliceWriter, 101 + offset: &mut file::Offset, 102 + ) -> Result<usize> { 103 + self.deref().write_to_slice(writer, offset) 104 + } 105 + } 106 + 107 + // Delegate for `Arc<T>`: Support a `Arc<T>` with no lock or an inner lock. 108 + impl<T> BinaryWriter for Arc<T> 109 + where 110 + T: BinaryWriter, 111 + { 112 + fn write_to_slice( 113 + &self, 114 + writer: &mut UserSliceWriter, 115 + offset: &mut file::Offset, 116 + ) -> Result<usize> { 117 + self.deref().write_to_slice(writer, offset) 118 + } 119 + } 120 + 121 + // Delegate for `Vec<T, A>`. 122 + impl<T, A> BinaryWriter for Vec<T, A> 123 + where 124 + T: AsBytes, 125 + A: Allocator, 126 + { 127 + fn write_to_slice( 128 + &self, 129 + writer: &mut UserSliceWriter, 130 + offset: &mut file::Offset, 131 + ) -> Result<usize> { 132 + let slice = self.as_slice(); 133 + 134 + // SAFETY: `T: AsBytes` allows us to treat `&[T]` as `&[u8]`. 135 + let buffer = unsafe { 136 + core::slice::from_raw_parts(slice.as_ptr().cast(), core::mem::size_of_val(slice)) 137 + }; 138 + 139 + writer.write_slice_file(buffer, offset) 41 140 } 42 141 } 43 142 ··· 188 79 let val = s.trim().parse::<T>().map_err(|_| EINVAL)?; 189 80 self.store(val, Relaxed); 190 81 Ok(()) 82 + } 83 + } 84 + 85 + /// Trait for types that can be constructed from a binary representation. 86 + /// 87 + /// See also [`BinaryReader`] for interior mutability. 88 + pub trait BinaryReaderMut { 89 + /// Reads the binary form of `self` from `reader`. 90 + /// 91 + /// Same as [`BinaryReader::read_from_slice`], but takes a mutable reference. 92 + /// 93 + /// `offset` is the requested offset into the binary representation of `self`. 94 + /// 95 + /// On success, returns the number of bytes read from `reader`. 96 + fn read_from_slice_mut( 97 + &mut self, 98 + reader: &mut UserSliceReader, 99 + offset: &mut file::Offset, 100 + ) -> Result<usize>; 101 + } 102 + 103 + // Base implementation for any `T: AsBytes + FromBytes`. 104 + impl<T: AsBytes + FromBytes> BinaryReaderMut for T { 105 + fn read_from_slice_mut( 106 + &mut self, 107 + reader: &mut UserSliceReader, 108 + offset: &mut file::Offset, 109 + ) -> Result<usize> { 110 + reader.read_slice_file(self.as_bytes_mut(), offset) 111 + } 112 + } 113 + 114 + // Delegate for `Box<T, A>`: Support a `Box<T, A>` with an outer lock. 115 + impl<T: ?Sized + BinaryReaderMut, A: Allocator> BinaryReaderMut for Box<T, A> { 116 + fn read_from_slice_mut( 117 + &mut self, 118 + reader: &mut UserSliceReader, 119 + offset: &mut file::Offset, 120 + ) -> Result<usize> { 121 + self.deref_mut().read_from_slice_mut(reader, offset) 122 + } 123 + } 124 + 125 + // Delegate for `Vec<T, A>`: Support a `Vec<T, A>` with an outer lock. 126 + impl<T, A> BinaryReaderMut for Vec<T, A> 127 + where 128 + T: AsBytes + FromBytes, 129 + A: Allocator, 130 + { 131 + fn read_from_slice_mut( 132 + &mut self, 133 + reader: &mut UserSliceReader, 134 + offset: &mut file::Offset, 135 + ) -> Result<usize> { 136 + let slice = self.as_mut_slice(); 137 + 138 + // SAFETY: `T: AsBytes + FromBytes` allows us to treat `&mut [T]` as `&mut [u8]`. 139 + let buffer = unsafe { 140 + core::slice::from_raw_parts_mut( 141 + slice.as_mut_ptr().cast(), 142 + core::mem::size_of_val(slice), 143 + ) 144 + }; 145 + 146 + reader.read_slice_file(buffer, offset) 147 + } 148 + } 149 + 150 + /// Trait for types that can be constructed from a binary representation. 151 + /// 152 + /// See also [`BinaryReaderMut`] for the mutable version. 153 + pub trait BinaryReader { 154 + /// Reads the binary form of `self` from `reader`. 155 + /// 156 + /// `offset` is the requested offset into the binary representation of `self`. 157 + /// 158 + /// On success, returns the number of bytes read from `reader`. 159 + fn read_from_slice( 160 + &self, 161 + reader: &mut UserSliceReader, 162 + offset: &mut file::Offset, 163 + ) -> Result<usize>; 164 + } 165 + 166 + // Delegate for `Mutex<T>`: Support a `T` with an outer `Mutex`. 167 + impl<T: BinaryReaderMut + Unpin> BinaryReader for Mutex<T> { 168 + fn read_from_slice( 169 + &self, 170 + reader: &mut UserSliceReader, 171 + offset: &mut file::Offset, 172 + ) -> Result<usize> { 173 + let mut this = self.lock(); 174 + 175 + this.read_from_slice_mut(reader, offset) 176 + } 177 + } 178 + 179 + // Delegate for `Box<T, A>`: Support a `Box<T, A>` with an inner lock. 180 + impl<T: ?Sized + BinaryReader, A: Allocator> BinaryReader for Box<T, A> { 181 + fn read_from_slice( 182 + &self, 183 + reader: &mut UserSliceReader, 184 + offset: &mut file::Offset, 185 + ) -> Result<usize> { 186 + self.deref().read_from_slice(reader, offset) 187 + } 188 + } 189 + 190 + // Delegate for `Pin<Box<T, A>>`: Support a `Pin<Box<T, A>>` with an inner lock. 191 + impl<T: ?Sized + BinaryReader, A: Allocator> BinaryReader for Pin<Box<T, A>> { 192 + fn read_from_slice( 193 + &self, 194 + reader: &mut UserSliceReader, 195 + offset: &mut file::Offset, 196 + ) -> Result<usize> { 197 + self.deref().read_from_slice(reader, offset) 198 + } 199 + } 200 + 201 + // Delegate for `Arc<T>`: Support an `Arc<T>` with an inner lock. 202 + impl<T: ?Sized + BinaryReader> BinaryReader for Arc<T> { 203 + fn read_from_slice( 204 + &self, 205 + reader: &mut UserSliceReader, 206 + offset: &mut file::Offset, 207 + ) -> Result<usize> { 208 + self.deref().read_from_slice(reader, offset) 191 209 } 192 210 }
+124 -8
rust/kernel/device.rs
··· 6 6 7 7 use crate::{ 8 8 bindings, fmt, 9 + prelude::*, 9 10 sync::aref::ARef, 10 11 types::{ForeignOwnable, Opaque}, 11 12 }; 12 - use core::{marker::PhantomData, ptr}; 13 + use core::{any::TypeId, marker::PhantomData, ptr}; 13 14 14 15 #[cfg(CONFIG_PRINTK)] 15 16 use crate::c_str; 16 17 use crate::str::CStrExt as _; 17 18 18 19 pub mod property; 20 + 21 + // Assert that we can `read()` / `write()` a `TypeId` instance from / into `struct driver_type`. 22 + static_assert!(core::mem::size_of::<bindings::driver_type>() >= core::mem::size_of::<TypeId>()); 19 23 20 24 /// The core representation of a device in the kernel's driver model. 21 25 /// ··· 202 198 } 203 199 204 200 impl Device<CoreInternal> { 205 - /// Store a pointer to the bound driver's private data. 206 - pub fn set_drvdata(&self, data: impl ForeignOwnable) { 201 + fn set_type_id<T: 'static>(&self) { 207 202 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 208 - unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) } 203 + let private = unsafe { (*self.as_raw()).p }; 204 + 205 + // SAFETY: For a bound device (implied by the `CoreInternal` device context), `private` is 206 + // guaranteed to be a valid pointer to a `struct device_private`. 207 + let driver_type = unsafe { &raw mut (*private).driver_type }; 208 + 209 + // SAFETY: `driver_type` is valid for (unaligned) writes of a `TypeId`. 210 + unsafe { 211 + driver_type 212 + .cast::<TypeId>() 213 + .write_unaligned(TypeId::of::<T>()) 214 + }; 215 + } 216 + 217 + /// Store a pointer to the bound driver's private data. 218 + pub fn set_drvdata<T: 'static>(&self, data: impl PinInit<T, Error>) -> Result { 219 + let data = KBox::pin_init(data, GFP_KERNEL)?; 220 + 221 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 222 + unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) }; 223 + self.set_type_id::<T>(); 224 + 225 + Ok(()) 209 226 } 210 227 211 228 /// Take ownership of the private data stored in this [`Device`]. ··· 236 211 /// - Must only be called once after a preceding call to [`Device::set_drvdata`]. 237 212 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 238 213 /// [`Device::set_drvdata`]. 239 - pub unsafe fn drvdata_obtain<T: ForeignOwnable>(&self) -> T { 214 + pub unsafe fn drvdata_obtain<T: 'static>(&self) -> Pin<KBox<T>> { 240 215 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 241 216 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) }; 217 + 218 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 219 + unsafe { bindings::dev_set_drvdata(self.as_raw(), core::ptr::null_mut()) }; 242 220 243 221 // SAFETY: 244 222 // - By the safety requirements of this function, `ptr` comes from a previous call to 245 223 // `into_foreign()`. 246 224 // - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()` 247 225 // in `into_foreign()`. 248 - unsafe { T::from_foreign(ptr.cast()) } 226 + unsafe { Pin::<KBox<T>>::from_foreign(ptr.cast()) } 249 227 } 250 228 251 229 /// Borrow the driver's private data bound to this [`Device`]. ··· 259 231 /// [`Device::drvdata_obtain`]. 260 232 /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 261 233 /// [`Device::set_drvdata`]. 262 - pub unsafe fn drvdata_borrow<T: ForeignOwnable>(&self) -> T::Borrowed<'_> { 234 + pub unsafe fn drvdata_borrow<T: 'static>(&self) -> Pin<&T> { 235 + // SAFETY: `drvdata_unchecked()` has the exact same safety requirements as the ones 236 + // required by this method. 237 + unsafe { self.drvdata_unchecked() } 238 + } 239 + } 240 + 241 + impl Device<Bound> { 242 + /// Borrow the driver's private data bound to this [`Device`]. 243 + /// 244 + /// # Safety 245 + /// 246 + /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before 247 + /// [`Device::drvdata_obtain`]. 248 + /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 249 + /// [`Device::set_drvdata`]. 250 + unsafe fn drvdata_unchecked<T: 'static>(&self) -> Pin<&T> { 263 251 // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 264 252 let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) }; 265 253 ··· 284 240 // `into_foreign()`. 285 241 // - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()` 286 242 // in `into_foreign()`. 287 - unsafe { T::borrow(ptr.cast()) } 243 + unsafe { Pin::<KBox<T>>::borrow(ptr.cast()) } 244 + } 245 + 246 + fn match_type_id<T: 'static>(&self) -> Result { 247 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 248 + let private = unsafe { (*self.as_raw()).p }; 249 + 250 + // SAFETY: For a bound device, `private` is guaranteed to be a valid pointer to a 251 + // `struct device_private`. 252 + let driver_type = unsafe { &raw mut (*private).driver_type }; 253 + 254 + // SAFETY: 255 + // - `driver_type` is valid for (unaligned) reads of a `TypeId`. 256 + // - A bound device guarantees that `driver_type` contains a valid `TypeId` value. 257 + let type_id = unsafe { driver_type.cast::<TypeId>().read_unaligned() }; 258 + 259 + if type_id != TypeId::of::<T>() { 260 + return Err(EINVAL); 261 + } 262 + 263 + Ok(()) 264 + } 265 + 266 + /// Access a driver's private data. 267 + /// 268 + /// Returns a pinned reference to the driver's private data or [`EINVAL`] if it doesn't match 269 + /// the asserted type `T`. 270 + pub fn drvdata<T: 'static>(&self) -> Result<Pin<&T>> { 271 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 272 + if unsafe { bindings::dev_get_drvdata(self.as_raw()) }.is_null() { 273 + return Err(ENOENT); 274 + } 275 + 276 + self.match_type_id::<T>()?; 277 + 278 + // SAFETY: 279 + // - The above check of `dev_get_drvdata()` guarantees that we are called after 280 + // `set_drvdata()` and before `drvdata_obtain()`. 281 + // - We've just checked that the type of the driver's private data is in fact `T`. 282 + Ok(unsafe { self.drvdata_unchecked() }) 288 283 } 289 284 } 290 285 ··· 594 511 impl DeviceContext for Core {} 595 512 impl DeviceContext for CoreInternal {} 596 513 impl DeviceContext for Normal {} 514 + 515 + /// Convert device references to bus device references. 516 + /// 517 + /// Bus devices can implement this trait to allow abstractions to provide the bus device in 518 + /// class device callbacks. 519 + /// 520 + /// This must not be used by drivers and is intended for bus and class device abstractions only. 521 + /// 522 + /// # Safety 523 + /// 524 + /// `AsBusDevice::OFFSET` must be the offset of the embedded base `struct device` field within a 525 + /// bus device structure. 526 + pub unsafe trait AsBusDevice<Ctx: DeviceContext>: AsRef<Device<Ctx>> { 527 + /// The relative offset to the device field. 528 + /// 529 + /// Use `offset_of!(bindings, field)` macro to avoid breakage. 530 + const OFFSET: usize; 531 + 532 + /// Convert a reference to [`Device`] into `Self`. 533 + /// 534 + /// # Safety 535 + /// 536 + /// `dev` must be contained in `Self`. 537 + unsafe fn from_device(dev: &Device<Ctx>) -> &Self 538 + where 539 + Self: Sized, 540 + { 541 + let raw = dev.as_raw(); 542 + // SAFETY: `raw - Self::OFFSET` is guaranteed by the safety requirements 543 + // to be a valid pointer to `Self`. 544 + unsafe { &*raw.byte_sub(Self::OFFSET).cast::<Self>() } 545 + } 546 + } 597 547 598 548 /// # Safety 599 549 ///
+15 -3
rust/kernel/devres.rs
··· 52 52 /// # Examples 53 53 /// 54 54 /// ```no_run 55 - /// # use kernel::{bindings, device::{Bound, Device}, devres::Devres, io::{Io, IoRaw}}; 56 - /// # use core::ops::Deref; 55 + /// use kernel::{ 56 + /// bindings, 57 + /// device::{ 58 + /// Bound, 59 + /// Device, 60 + /// }, 61 + /// devres::Devres, 62 + /// io::{ 63 + /// Io, 64 + /// IoRaw, 65 + /// PhysAddr, 66 + /// }, 67 + /// }; 68 + /// use core::ops::Deref; 57 69 /// 58 70 /// // See also [`pci::Bar`] for a real example. 59 71 /// struct IoMem<const SIZE: usize>(IoRaw<SIZE>); ··· 78 66 /// unsafe fn new(paddr: usize) -> Result<Self>{ 79 67 /// // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is 80 68 /// // valid for `ioremap`. 81 - /// let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) }; 69 + /// let addr = unsafe { bindings::ioremap(paddr as PhysAddr, SIZE) }; 82 70 /// if addr.is_null() { 83 71 /// return Err(ENOMEM); 84 72 /// }
+16 -13
rust/kernel/dma.rs
··· 12 12 sync::aref::ARef, 13 13 transmute::{AsBytes, FromBytes}, 14 14 }; 15 + use core::ptr::NonNull; 15 16 16 17 /// DMA address type. 17 18 /// ··· 359 358 dev: ARef<device::Device>, 360 359 dma_handle: DmaAddress, 361 360 count: usize, 362 - cpu_addr: *mut T, 361 + cpu_addr: NonNull<T>, 363 362 dma_attrs: Attrs, 364 363 } 365 364 ··· 393 392 .ok_or(EOVERFLOW)?; 394 393 let mut dma_handle = 0; 395 394 // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. 396 - let ret = unsafe { 395 + let addr = unsafe { 397 396 bindings::dma_alloc_attrs( 398 397 dev.as_raw(), 399 398 size, ··· 402 401 dma_attrs.as_raw(), 403 402 ) 404 403 }; 405 - if ret.is_null() { 406 - return Err(ENOMEM); 407 - } 404 + let addr = NonNull::new(addr).ok_or(ENOMEM)?; 408 405 // INVARIANT: 409 406 // - We just successfully allocated a coherent region which is accessible for 410 407 // `count` elements, hence the cpu address is valid. We also hold a refcounted reference ··· 413 414 dev: dev.into(), 414 415 dma_handle, 415 416 count, 416 - cpu_addr: ret.cast::<T>(), 417 + cpu_addr: addr.cast(), 417 418 dma_attrs, 418 419 }) 419 420 } ··· 445 446 446 447 /// Returns the base address to the allocated region in the CPU's virtual address space. 447 448 pub fn start_ptr(&self) -> *const T { 448 - self.cpu_addr 449 + self.cpu_addr.as_ptr() 449 450 } 450 451 451 452 /// Returns the base address to the allocated region in the CPU's virtual address space as 452 453 /// a mutable pointer. 453 454 pub fn start_ptr_mut(&mut self) -> *mut T { 454 - self.cpu_addr 455 + self.cpu_addr.as_ptr() 455 456 } 456 457 457 458 /// Returns a DMA handle which may be given to the device as the DMA address base of ··· 504 505 // data is also guaranteed by the safety requirements of the function. 505 506 // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked 506 507 // that `self.count` won't overflow early in the constructor. 507 - Ok(unsafe { core::slice::from_raw_parts(self.cpu_addr.add(offset), count) }) 508 + Ok(unsafe { core::slice::from_raw_parts(self.start_ptr().add(offset), count) }) 508 509 } 509 510 510 511 /// Performs the same functionality as [`CoherentAllocation::as_slice`], except that a mutable ··· 524 525 // data is also guaranteed by the safety requirements of the function. 525 526 // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked 526 527 // that `self.count` won't overflow early in the constructor. 527 - Ok(unsafe { core::slice::from_raw_parts_mut(self.cpu_addr.add(offset), count) }) 528 + Ok(unsafe { core::slice::from_raw_parts_mut(self.start_ptr_mut().add(offset), count) }) 528 529 } 529 530 530 531 /// Writes data to the region starting from `offset`. `offset` is in units of `T`, not the ··· 556 557 // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked 557 558 // that `self.count` won't overflow early in the constructor. 558 559 unsafe { 559 - core::ptr::copy_nonoverlapping(src.as_ptr(), self.cpu_addr.add(offset), src.len()) 560 + core::ptr::copy_nonoverlapping( 561 + src.as_ptr(), 562 + self.start_ptr_mut().add(offset), 563 + src.len(), 564 + ) 560 565 }; 561 566 Ok(()) 562 567 } ··· 579 576 // and we've just checked that the range and index is within bounds. 580 577 // - `offset` can't overflow since it is smaller than `self.count` and we've checked 581 578 // that `self.count` won't overflow early in the constructor. 582 - Ok(unsafe { self.cpu_addr.add(offset) }) 579 + Ok(unsafe { self.cpu_addr.as_ptr().add(offset) }) 583 580 } 584 581 585 582 /// Reads the value of `field` and ensures that its type is [`FromBytes`]. ··· 640 637 bindings::dma_free_attrs( 641 638 self.dev.as_raw(), 642 639 size, 643 - self.cpu_addr.cast(), 640 + self.start_ptr_mut().cast(), 644 641 self.dma_handle, 645 642 self.dma_attrs.as_raw(), 646 643 )
+2 -2
rust/kernel/driver.rs
··· 24 24 //! const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None; 25 25 //! 26 26 //! /// Driver probe. 27 - //! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 27 + //! fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>; 28 28 //! 29 29 //! /// Driver unbind (optional). 30 30 //! fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) { ··· 35 35 //! 36 36 //! For specific examples see [`auxiliary::Driver`], [`pci::Driver`] and [`platform::Driver`]. 37 37 //! 38 - //! The `probe()` callback should return a `Result<Pin<KBox<Self>>>`, i.e. the driver's private 38 + //! The `probe()` callback should return a `impl PinInit<Self, Error>`, i.e. the driver's private 39 39 //! data. The bus abstraction should store the pointer in the corresponding bus device. The generic 40 40 //! [`Device`] infrastructure provides common helpers for this purpose on its 41 41 //! [`Device<CoreInternal>`] implementation.
+5
rust/kernel/fs/file.rs
··· 17 17 }; 18 18 use core::ptr; 19 19 20 + /// Primitive type representing the offset within a [`File`]. 21 + /// 22 + /// Type alias for `bindings::loff_t`. 23 + pub type Offset = bindings::loff_t; 24 + 20 25 /// Flags associated with a [`File`]. 21 26 pub mod flags { 22 27 /// File is opened in append mode.
+586
rust/kernel/i2c.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! I2C Driver subsystem 4 + 5 + // I2C Driver abstractions. 6 + use crate::{ 7 + acpi, 8 + container_of, 9 + device, 10 + device_id::{ 11 + RawDeviceId, 12 + RawDeviceIdIndex, // 13 + }, 14 + devres::Devres, 15 + driver, 16 + error::*, 17 + of, 18 + prelude::*, 19 + types::{ 20 + AlwaysRefCounted, 21 + Opaque, // 22 + }, // 23 + }; 24 + 25 + use core::{ 26 + marker::PhantomData, 27 + mem::offset_of, 28 + ptr::{ 29 + from_ref, 30 + NonNull, // 31 + }, // 32 + }; 33 + 34 + use kernel::types::ARef; 35 + 36 + /// An I2C device id table. 37 + #[repr(transparent)] 38 + #[derive(Clone, Copy)] 39 + pub struct DeviceId(bindings::i2c_device_id); 40 + 41 + impl DeviceId { 42 + const I2C_NAME_SIZE: usize = 20; 43 + 44 + /// Create a new device id from an I2C 'id' string. 45 + #[inline(always)] 46 + pub const fn new(id: &'static CStr) -> Self { 47 + let src = id.to_bytes_with_nul(); 48 + build_assert!(src.len() <= Self::I2C_NAME_SIZE, "ID exceeds 20 bytes"); 49 + let mut i2c: bindings::i2c_device_id = pin_init::zeroed(); 50 + let mut i = 0; 51 + while i < src.len() { 52 + i2c.name[i] = src[i]; 53 + i += 1; 54 + } 55 + 56 + Self(i2c) 57 + } 58 + } 59 + 60 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `i2c_device_id` and does not add 61 + // additional invariants, so it's safe to transmute to `RawType`. 62 + unsafe impl RawDeviceId for DeviceId { 63 + type RawType = bindings::i2c_device_id; 64 + } 65 + 66 + // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 67 + unsafe impl RawDeviceIdIndex for DeviceId { 68 + const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::i2c_device_id, driver_data); 69 + 70 + fn index(&self) -> usize { 71 + self.0.driver_data 72 + } 73 + } 74 + 75 + /// IdTable type for I2C 76 + pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; 77 + 78 + /// Create a I2C `IdTable` with its alias for modpost. 79 + #[macro_export] 80 + macro_rules! i2c_device_table { 81 + ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { 82 + const $table_name: $crate::device_id::IdArray< 83 + $crate::i2c::DeviceId, 84 + $id_info_type, 85 + { $table_data.len() }, 86 + > = $crate::device_id::IdArray::new($table_data); 87 + 88 + $crate::module_device_table!("i2c", $module_table_name, $table_name); 89 + }; 90 + } 91 + 92 + /// An adapter for the registration of I2C drivers. 93 + pub struct Adapter<T: Driver>(T); 94 + 95 + // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 96 + // a preceding call to `register` has been successful. 97 + unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 98 + type RegType = bindings::i2c_driver; 99 + 100 + unsafe fn register( 101 + idrv: &Opaque<Self::RegType>, 102 + name: &'static CStr, 103 + module: &'static ThisModule, 104 + ) -> Result { 105 + build_assert!( 106 + T::ACPI_ID_TABLE.is_some() || T::OF_ID_TABLE.is_some() || T::I2C_ID_TABLE.is_some(), 107 + "At least one of ACPI/OF/Legacy tables must be present when registering an i2c driver" 108 + ); 109 + 110 + let i2c_table = match T::I2C_ID_TABLE { 111 + Some(table) => table.as_ptr(), 112 + None => core::ptr::null(), 113 + }; 114 + 115 + let of_table = match T::OF_ID_TABLE { 116 + Some(table) => table.as_ptr(), 117 + None => core::ptr::null(), 118 + }; 119 + 120 + let acpi_table = match T::ACPI_ID_TABLE { 121 + Some(table) => table.as_ptr(), 122 + None => core::ptr::null(), 123 + }; 124 + 125 + // SAFETY: It's safe to set the fields of `struct i2c_client` on initialization. 126 + unsafe { 127 + (*idrv.get()).driver.name = name.as_char_ptr(); 128 + (*idrv.get()).probe = Some(Self::probe_callback); 129 + (*idrv.get()).remove = Some(Self::remove_callback); 130 + (*idrv.get()).shutdown = Some(Self::shutdown_callback); 131 + (*idrv.get()).id_table = i2c_table; 132 + (*idrv.get()).driver.of_match_table = of_table; 133 + (*idrv.get()).driver.acpi_match_table = acpi_table; 134 + } 135 + 136 + // SAFETY: `idrv` is guaranteed to be a valid `RegType`. 137 + to_result(unsafe { bindings::i2c_register_driver(module.0, idrv.get()) }) 138 + } 139 + 140 + unsafe fn unregister(idrv: &Opaque<Self::RegType>) { 141 + // SAFETY: `idrv` is guaranteed to be a valid `RegType`. 142 + unsafe { bindings::i2c_del_driver(idrv.get()) } 143 + } 144 + } 145 + 146 + impl<T: Driver + 'static> Adapter<T> { 147 + extern "C" fn probe_callback(idev: *mut bindings::i2c_client) -> kernel::ffi::c_int { 148 + // SAFETY: The I2C bus only ever calls the probe callback with a valid pointer to a 149 + // `struct i2c_client`. 150 + // 151 + // INVARIANT: `idev` is valid for the duration of `probe_callback()`. 152 + let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal>>() }; 153 + 154 + let info = 155 + Self::i2c_id_info(idev).or_else(|| <Self as driver::Adapter>::id_info(idev.as_ref())); 156 + 157 + from_result(|| { 158 + let data = T::probe(idev, info); 159 + 160 + idev.as_ref().set_drvdata(data)?; 161 + Ok(0) 162 + }) 163 + } 164 + 165 + extern "C" fn remove_callback(idev: *mut bindings::i2c_client) { 166 + // SAFETY: `idev` is a valid pointer to a `struct i2c_client`. 167 + let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal>>() }; 168 + 169 + // SAFETY: `remove_callback` is only ever called after a successful call to 170 + // `probe_callback`, hence it's guaranteed that `I2cClient::set_drvdata()` has been called 171 + // and stored a `Pin<KBox<T>>`. 172 + let data = unsafe { idev.as_ref().drvdata_obtain::<T>() }; 173 + 174 + T::unbind(idev, data.as_ref()); 175 + } 176 + 177 + extern "C" fn shutdown_callback(idev: *mut bindings::i2c_client) { 178 + // SAFETY: `shutdown_callback` is only ever called for a valid `idev` 179 + let idev = unsafe { &*idev.cast::<I2cClient<device::CoreInternal>>() }; 180 + 181 + // SAFETY: `shutdown_callback` is only ever called after a successful call to 182 + // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 183 + // and stored a `Pin<KBox<T>>`. 184 + let data = unsafe { idev.as_ref().drvdata_obtain::<T>() }; 185 + 186 + T::shutdown(idev, data.as_ref()); 187 + } 188 + 189 + /// The [`i2c::IdTable`] of the corresponding driver. 190 + fn i2c_id_table() -> Option<IdTable<<Self as driver::Adapter>::IdInfo>> { 191 + T::I2C_ID_TABLE 192 + } 193 + 194 + /// Returns the driver's private data from the matching entry in the [`i2c::IdTable`], if any. 195 + /// 196 + /// If this returns `None`, it means there is no match with an entry in the [`i2c::IdTable`]. 197 + fn i2c_id_info(dev: &I2cClient) -> Option<&'static <Self as driver::Adapter>::IdInfo> { 198 + let table = Self::i2c_id_table()?; 199 + 200 + // SAFETY: 201 + // - `table` has static lifetime, hence it's valid for reads 202 + // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`. 203 + let raw_id = unsafe { bindings::i2c_match_id(table.as_ptr(), dev.as_raw()) }; 204 + 205 + if raw_id.is_null() { 206 + return None; 207 + } 208 + 209 + // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct i2c_device_id` and 210 + // does not add additional invariants, so it's safe to transmute. 211 + let id = unsafe { &*raw_id.cast::<DeviceId>() }; 212 + 213 + Some(table.info(<DeviceId as RawDeviceIdIndex>::index(id))) 214 + } 215 + } 216 + 217 + impl<T: Driver + 'static> driver::Adapter for Adapter<T> { 218 + type IdInfo = T::IdInfo; 219 + 220 + fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> { 221 + T::OF_ID_TABLE 222 + } 223 + 224 + fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>> { 225 + T::ACPI_ID_TABLE 226 + } 227 + } 228 + 229 + /// Declares a kernel module that exposes a single i2c driver. 230 + /// 231 + /// # Examples 232 + /// 233 + /// ```ignore 234 + /// kernel::module_i2c_driver! { 235 + /// type: MyDriver, 236 + /// name: "Module name", 237 + /// authors: ["Author name"], 238 + /// description: "Description", 239 + /// license: "GPL v2", 240 + /// } 241 + /// ``` 242 + #[macro_export] 243 + macro_rules! module_i2c_driver { 244 + ($($f:tt)*) => { 245 + $crate::module_driver!(<T>, $crate::i2c::Adapter<T>, { $($f)* }); 246 + }; 247 + } 248 + 249 + /// The i2c driver trait. 250 + /// 251 + /// Drivers must implement this trait in order to get a i2c driver registered. 252 + /// 253 + /// # Example 254 + /// 255 + ///``` 256 + /// # use kernel::{acpi, bindings, c_str, device::Core, i2c, of}; 257 + /// 258 + /// struct MyDriver; 259 + /// 260 + /// kernel::acpi_device_table!( 261 + /// ACPI_TABLE, 262 + /// MODULE_ACPI_TABLE, 263 + /// <MyDriver as i2c::Driver>::IdInfo, 264 + /// [ 265 + /// (acpi::DeviceId::new(c_str!("LNUXBEEF")), ()) 266 + /// ] 267 + /// ); 268 + /// 269 + /// kernel::i2c_device_table!( 270 + /// I2C_TABLE, 271 + /// MODULE_I2C_TABLE, 272 + /// <MyDriver as i2c::Driver>::IdInfo, 273 + /// [ 274 + /// (i2c::DeviceId::new(c_str!("rust_driver_i2c")), ()) 275 + /// ] 276 + /// ); 277 + /// 278 + /// kernel::of_device_table!( 279 + /// OF_TABLE, 280 + /// MODULE_OF_TABLE, 281 + /// <MyDriver as i2c::Driver>::IdInfo, 282 + /// [ 283 + /// (of::DeviceId::new(c_str!("test,device")), ()) 284 + /// ] 285 + /// ); 286 + /// 287 + /// impl i2c::Driver for MyDriver { 288 + /// type IdInfo = (); 289 + /// const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE); 290 + /// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); 291 + /// const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); 292 + /// 293 + /// fn probe( 294 + /// _idev: &i2c::I2cClient<Core>, 295 + /// _id_info: Option<&Self::IdInfo>, 296 + /// ) -> impl PinInit<Self, Error> { 297 + /// Err(ENODEV) 298 + /// } 299 + /// 300 + /// fn shutdown(_idev: &i2c::I2cClient<Core>, this: Pin<&Self>) { 301 + /// } 302 + /// } 303 + ///``` 304 + pub trait Driver: Send { 305 + /// The type holding information about each device id supported by the driver. 306 + // TODO: Use `associated_type_defaults` once stabilized: 307 + // 308 + // ``` 309 + // type IdInfo: 'static = (); 310 + // ``` 311 + type IdInfo: 'static; 312 + 313 + /// The table of device ids supported by the driver. 314 + const I2C_ID_TABLE: Option<IdTable<Self::IdInfo>> = None; 315 + 316 + /// The table of OF device ids supported by the driver. 317 + const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None; 318 + 319 + /// The table of ACPI device ids supported by the driver. 320 + const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None; 321 + 322 + /// I2C driver probe. 323 + /// 324 + /// Called when a new i2c client is added or discovered. 325 + /// Implementers should attempt to initialize the client here. 326 + fn probe( 327 + dev: &I2cClient<device::Core>, 328 + id_info: Option<&Self::IdInfo>, 329 + ) -> impl PinInit<Self, Error>; 330 + 331 + /// I2C driver shutdown. 332 + /// 333 + /// Called by the kernel during system reboot or power-off to allow the [`Driver`] to bring the 334 + /// [`I2cClient`] into a safe state. Implementing this callback is optional. 335 + /// 336 + /// Typical actions include stopping transfers, disabling interrupts, or resetting the hardware 337 + /// to prevent undesired behavior during shutdown. 338 + /// 339 + /// This callback is distinct from final resource cleanup, as the driver instance remains valid 340 + /// after it returns. Any deallocation or teardown of driver-owned resources should instead be 341 + /// handled in `Self::drop`. 342 + fn shutdown(dev: &I2cClient<device::Core>, this: Pin<&Self>) { 343 + let _ = (dev, this); 344 + } 345 + 346 + /// I2C driver unbind. 347 + /// 348 + /// Called when the [`I2cClient`] is unbound from its bound [`Driver`]. Implementing this 349 + /// callback is optional. 350 + /// 351 + /// This callback serves as a place for drivers to perform teardown operations that require a 352 + /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O 353 + /// operations to gracefully tear down the device. 354 + /// 355 + /// Otherwise, release operations for driver resources should be performed in `Self::drop`. 356 + fn unbind(dev: &I2cClient<device::Core>, this: Pin<&Self>) { 357 + let _ = (dev, this); 358 + } 359 + } 360 + 361 + /// The i2c adapter representation. 362 + /// 363 + /// This structure represents the Rust abstraction for a C `struct i2c_adapter`. The 364 + /// implementation abstracts the usage of an existing C `struct i2c_adapter` that 365 + /// gets passed from the C side 366 + /// 367 + /// # Invariants 368 + /// 369 + /// A [`I2cAdapter`] instance represents a valid `struct i2c_adapter` created by the C portion of 370 + /// the kernel. 371 + #[repr(transparent)] 372 + pub struct I2cAdapter<Ctx: device::DeviceContext = device::Normal>( 373 + Opaque<bindings::i2c_adapter>, 374 + PhantomData<Ctx>, 375 + ); 376 + 377 + impl<Ctx: device::DeviceContext> I2cAdapter<Ctx> { 378 + fn as_raw(&self) -> *mut bindings::i2c_adapter { 379 + self.0.get() 380 + } 381 + } 382 + 383 + impl I2cAdapter { 384 + /// Returns the I2C Adapter index. 385 + #[inline] 386 + pub fn index(&self) -> i32 { 387 + // SAFETY: `self.as_raw` is a valid pointer to a `struct i2c_adapter`. 388 + unsafe { (*self.as_raw()).nr } 389 + } 390 + 391 + /// Gets pointer to an `i2c_adapter` by index. 392 + pub fn get(index: i32) -> Result<ARef<Self>> { 393 + // SAFETY: `index` must refer to a valid I2C adapter; the kernel 394 + // guarantees that `i2c_get_adapter(index)` returns either a valid 395 + // pointer or NULL. `NonNull::new` guarantees the correct check. 396 + let adapter = NonNull::new(unsafe { bindings::i2c_get_adapter(index) }).ok_or(ENODEV)?; 397 + 398 + // SAFETY: `adapter` is non-null and points to a live `i2c_adapter`. 399 + // `I2cAdapter` is #[repr(transparent)], so this cast is valid. 400 + Ok(unsafe { (&*adapter.as_ptr().cast::<I2cAdapter<device::Normal>>()).into() }) 401 + } 402 + } 403 + 404 + // SAFETY: `I2cAdapter` is a transparent wrapper of a type that doesn't depend on 405 + // `I2cAdapter`'s generic argument. 406 + kernel::impl_device_context_deref!(unsafe { I2cAdapter }); 407 + kernel::impl_device_context_into_aref!(I2cAdapter); 408 + 409 + // SAFETY: Instances of `I2cAdapter` are always reference-counted. 410 + unsafe impl crate::types::AlwaysRefCounted for I2cAdapter { 411 + fn inc_ref(&self) { 412 + // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. 413 + unsafe { bindings::i2c_get_adapter(self.index()) }; 414 + } 415 + 416 + unsafe fn dec_ref(obj: NonNull<Self>) { 417 + // SAFETY: The safety requirements guarantee that the refcount is non-zero. 418 + unsafe { bindings::i2c_put_adapter(obj.as_ref().as_raw()) } 419 + } 420 + } 421 + 422 + /// The i2c board info representation 423 + /// 424 + /// This structure represents the Rust abstraction for a C `struct i2c_board_info` structure, 425 + /// which is used for manual I2C client creation. 426 + #[repr(transparent)] 427 + pub struct I2cBoardInfo(bindings::i2c_board_info); 428 + 429 + impl I2cBoardInfo { 430 + const I2C_TYPE_SIZE: usize = 20; 431 + /// Create a new [`I2cBoardInfo`] for a kernel driver. 432 + #[inline(always)] 433 + pub const fn new(type_: &'static CStr, addr: u16) -> Self { 434 + let src = type_.to_bytes_with_nul(); 435 + build_assert!(src.len() <= Self::I2C_TYPE_SIZE, "Type exceeds 20 bytes"); 436 + let mut i2c_board_info: bindings::i2c_board_info = pin_init::zeroed(); 437 + let mut i: usize = 0; 438 + while i < src.len() { 439 + i2c_board_info.type_[i] = src[i]; 440 + i += 1; 441 + } 442 + 443 + i2c_board_info.addr = addr; 444 + Self(i2c_board_info) 445 + } 446 + 447 + fn as_raw(&self) -> *const bindings::i2c_board_info { 448 + from_ref(&self.0) 449 + } 450 + } 451 + 452 + /// The i2c client representation. 453 + /// 454 + /// This structure represents the Rust abstraction for a C `struct i2c_client`. The 455 + /// implementation abstracts the usage of an existing C `struct i2c_client` that 456 + /// gets passed from the C side 457 + /// 458 + /// # Invariants 459 + /// 460 + /// A [`I2cClient`] instance represents a valid `struct i2c_client` created by the C portion of 461 + /// the kernel. 462 + #[repr(transparent)] 463 + pub struct I2cClient<Ctx: device::DeviceContext = device::Normal>( 464 + Opaque<bindings::i2c_client>, 465 + PhantomData<Ctx>, 466 + ); 467 + 468 + impl<Ctx: device::DeviceContext> I2cClient<Ctx> { 469 + fn as_raw(&self) -> *mut bindings::i2c_client { 470 + self.0.get() 471 + } 472 + } 473 + 474 + // SAFETY: `I2cClient` is a transparent wrapper of `struct i2c_client`. 475 + // The offset is guaranteed to point to a valid device field inside `I2cClient`. 476 + unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for I2cClient<Ctx> { 477 + const OFFSET: usize = offset_of!(bindings::i2c_client, dev); 478 + } 479 + 480 + // SAFETY: `I2cClient` is a transparent wrapper of a type that doesn't depend on 481 + // `I2cClient`'s generic argument. 482 + kernel::impl_device_context_deref!(unsafe { I2cClient }); 483 + kernel::impl_device_context_into_aref!(I2cClient); 484 + 485 + // SAFETY: Instances of `I2cClient` are always reference-counted. 486 + unsafe impl AlwaysRefCounted for I2cClient { 487 + fn inc_ref(&self) { 488 + // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. 489 + unsafe { bindings::get_device(self.as_ref().as_raw()) }; 490 + } 491 + 492 + unsafe fn dec_ref(obj: NonNull<Self>) { 493 + // SAFETY: The safety requirements guarantee that the refcount is non-zero. 494 + unsafe { bindings::put_device(&raw mut (*obj.as_ref().as_raw()).dev) } 495 + } 496 + } 497 + 498 + impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for I2cClient<Ctx> { 499 + fn as_ref(&self) -> &device::Device<Ctx> { 500 + let raw = self.as_raw(); 501 + // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid 502 + // `struct i2c_client`. 503 + let dev = unsafe { &raw mut (*raw).dev }; 504 + 505 + // SAFETY: `dev` points to a valid `struct device`. 506 + unsafe { device::Device::from_raw(dev) } 507 + } 508 + } 509 + 510 + impl<Ctx: device::DeviceContext> TryFrom<&device::Device<Ctx>> for &I2cClient<Ctx> { 511 + type Error = kernel::error::Error; 512 + 513 + fn try_from(dev: &device::Device<Ctx>) -> Result<Self, Self::Error> { 514 + // SAFETY: By the type invariant of `Device`, `dev.as_raw()` is a valid pointer to a 515 + // `struct device`. 516 + if unsafe { bindings::i2c_verify_client(dev.as_raw()).is_null() } { 517 + return Err(EINVAL); 518 + } 519 + 520 + // SAFETY: We've just verified that the type of `dev` equals to 521 + // `bindings::i2c_client_type`, hence `dev` must be embedded in a valid 522 + // `struct i2c_client` as guaranteed by the corresponding C code. 523 + let idev = unsafe { container_of!(dev.as_raw(), bindings::i2c_client, dev) }; 524 + 525 + // SAFETY: `idev` is a valid pointer to a `struct i2c_client`. 526 + Ok(unsafe { &*idev.cast() }) 527 + } 528 + } 529 + 530 + // SAFETY: A `I2cClient` is always reference-counted and can be released from any thread. 531 + unsafe impl Send for I2cClient {} 532 + 533 + // SAFETY: `I2cClient` can be shared among threads because all methods of `I2cClient` 534 + // (i.e. `I2cClient<Normal>) are thread safe. 535 + unsafe impl Sync for I2cClient {} 536 + 537 + /// The registration of an i2c client device. 538 + /// 539 + /// This type represents the registration of a [`struct i2c_client`]. When an instance of this 540 + /// type is dropped, its respective i2c client device will be unregistered from the system. 541 + /// 542 + /// # Invariants 543 + /// 544 + /// `self.0` always holds a valid pointer to an initialized and registered 545 + /// [`struct i2c_client`]. 546 + #[repr(transparent)] 547 + pub struct Registration(NonNull<bindings::i2c_client>); 548 + 549 + impl Registration { 550 + /// The C `i2c_new_client_device` function wrapper for manual I2C client creation. 551 + pub fn new<'a>( 552 + i2c_adapter: &I2cAdapter, 553 + i2c_board_info: &I2cBoardInfo, 554 + parent_dev: &'a device::Device<device::Bound>, 555 + ) -> impl PinInit<Devres<Self>, Error> + 'a { 556 + Devres::new(parent_dev, Self::try_new(i2c_adapter, i2c_board_info)) 557 + } 558 + 559 + fn try_new(i2c_adapter: &I2cAdapter, i2c_board_info: &I2cBoardInfo) -> Result<Self> { 560 + // SAFETY: the kernel guarantees that `i2c_new_client_device()` returns either a valid 561 + // pointer or NULL. `from_err_ptr` separates errors. Following `NonNull::new` 562 + // checks for NULL. 563 + let raw_dev = from_err_ptr(unsafe { 564 + bindings::i2c_new_client_device(i2c_adapter.as_raw(), i2c_board_info.as_raw()) 565 + })?; 566 + 567 + let dev_ptr = NonNull::new(raw_dev).ok_or(ENODEV)?; 568 + 569 + Ok(Self(dev_ptr)) 570 + } 571 + } 572 + 573 + impl Drop for Registration { 574 + fn drop(&mut self) { 575 + // SAFETY: `Drop` is only called for a valid `Registration`, which by invariant 576 + // always contains a non-null pointer to an `i2c_client`. 577 + unsafe { bindings::i2c_unregister_device(self.0.as_ptr()) } 578 + } 579 + } 580 + 581 + // SAFETY: A `Registration` of a `struct i2c_client` can be released from any thread. 582 + unsafe impl Send for Registration {} 583 + 584 + // SAFETY: `Registration` offers no interior mutability (no mutation through &self 585 + // and no mutable access is exposed) 586 + unsafe impl Sync for Registration {}
+27 -5
rust/kernel/io.rs
··· 4 4 //! 5 5 //! C header: [`include/asm-generic/io.h`](srctree/include/asm-generic/io.h) 6 6 7 - use crate::error::{code::EINVAL, Result}; 8 - use crate::{bindings, build_assert, ffi::c_void}; 7 + use crate::{ 8 + bindings, 9 + prelude::*, // 10 + }; 9 11 10 12 pub mod mem; 11 13 pub mod poll; 12 14 pub mod resource; 13 15 14 16 pub use resource::Resource; 17 + 18 + /// Physical address type. 19 + /// 20 + /// This is a type alias to either `u32` or `u64` depending on the config option 21 + /// `CONFIG_PHYS_ADDR_T_64BIT`, and it can be a u64 even on 32-bit architectures. 22 + pub type PhysAddr = bindings::phys_addr_t; 23 + 24 + /// Resource Size type. 25 + /// 26 + /// This is a type alias to either `u32` or `u64` depending on the config option 27 + /// `CONFIG_PHYS_ADDR_T_64BIT`, and it can be a u64 even on 32-bit architectures. 28 + pub type ResourceSize = bindings::resource_size_t; 15 29 16 30 /// Raw representation of an MMIO region. 17 31 /// ··· 76 62 /// # Examples 77 63 /// 78 64 /// ```no_run 79 - /// # use kernel::{bindings, ffi::c_void, io::{Io, IoRaw}}; 80 - /// # use core::ops::Deref; 65 + /// use kernel::{ 66 + /// bindings, 67 + /// ffi::c_void, 68 + /// io::{ 69 + /// Io, 70 + /// IoRaw, 71 + /// PhysAddr, 72 + /// }, 73 + /// }; 74 + /// use core::ops::Deref; 81 75 /// 82 76 /// // See also [`pci::Bar`] for a real example. 83 77 /// struct IoMem<const SIZE: usize>(IoRaw<SIZE>); ··· 98 76 /// unsafe fn new(paddr: usize) -> Result<Self>{ 99 77 /// // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is 100 78 /// // valid for `ioremap`. 101 - /// let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) }; 79 + /// let addr = unsafe { bindings::ioremap(paddr as PhysAddr, SIZE) }; 102 80 /// if addr.is_null() { 103 81 /// return Err(ENOMEM); 104 82 /// }
+22 -14
rust/kernel/io/mem.rs
··· 4 4 5 5 use core::ops::Deref; 6 6 7 - use crate::c_str; 8 - use crate::device::Bound; 9 - use crate::device::Device; 10 - use crate::devres::Devres; 11 - use crate::io; 12 - use crate::io::resource::Region; 13 - use crate::io::resource::Resource; 14 - use crate::io::Io; 15 - use crate::io::IoRaw; 16 - use crate::prelude::*; 7 + use crate::{ 8 + c_str, 9 + device::{ 10 + Bound, 11 + Device, // 12 + }, 13 + devres::Devres, 14 + io::{ 15 + self, 16 + resource::{ 17 + Region, 18 + Resource, // 19 + }, 20 + Io, 21 + IoRaw, // 22 + }, 23 + prelude::*, 24 + }; 17 25 18 26 /// An IO request for a specific device and resource. 19 27 pub struct IoRequest<'a> { ··· 61 53 /// fn probe( 62 54 /// pdev: &platform::Device<Core>, 63 55 /// info: Option<&Self::IdInfo>, 64 - /// ) -> Result<Pin<KBox<Self>>> { 56 + /// ) -> impl PinInit<Self, Error> { 65 57 /// let offset = 0; // Some offset. 66 58 /// 67 59 /// // If the size is known at compile time, use [`Self::iomap_sized`]. ··· 78 70 /// 79 71 /// io.write32_relaxed(data, offset); 80 72 /// 81 - /// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) 73 + /// # Ok(SampleDriver) 82 74 /// } 83 75 /// } 84 76 /// ``` ··· 119 111 /// fn probe( 120 112 /// pdev: &platform::Device<Core>, 121 113 /// info: Option<&Self::IdInfo>, 122 - /// ) -> Result<Pin<KBox<Self>>> { 114 + /// ) -> impl PinInit<Self, Error> { 123 115 /// let offset = 0; // Some offset. 124 116 /// 125 117 /// // Unlike [`Self::iomap_sized`], here the size of the memory region ··· 136 128 /// 137 129 /// io.try_write32_relaxed(data, offset)?; 138 130 /// 139 - /// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) 131 + /// # Ok(SampleDriver) 140 132 /// } 141 133 /// } 142 134 /// ```
+81 -12
rust/kernel/io/poll.rs
··· 5 5 //! C header: [`include/linux/iopoll.h`](srctree/include/linux/iopoll.h). 6 6 7 7 use crate::{ 8 - error::{code::*, Result}, 8 + prelude::*, 9 9 processor::cpu_relax, 10 10 task::might_sleep, 11 - time::{delay::fsleep, Delta, Instant, Monotonic}, 11 + time::{ 12 + delay::{ 13 + fsleep, 14 + udelay, // 15 + }, 16 + Delta, 17 + Instant, 18 + Monotonic, // 19 + }, 12 20 }; 13 21 14 22 /// Polls periodically until a condition is met, an error occurs, ··· 50 42 /// 51 43 /// const HW_READY: u16 = 0x01; 52 44 /// 53 - /// fn wait_for_hardware<const SIZE: usize>(io: &Io<SIZE>) -> Result<()> { 54 - /// match read_poll_timeout( 45 + /// fn wait_for_hardware<const SIZE: usize>(io: &Io<SIZE>) -> Result { 46 + /// read_poll_timeout( 55 47 /// // The `op` closure reads the value of a specific status register. 56 48 /// || io.try_read16(0x1000), 57 49 /// // The `cond` closure takes a reference to the value returned by `op` ··· 59 51 /// |val: &u16| *val == HW_READY, 60 52 /// Delta::from_millis(50), 61 53 /// Delta::from_secs(3), 62 - /// ) { 63 - /// Ok(_) => { 64 - /// // The hardware is ready. The returned value of the `op` closure 65 - /// // isn't used. 66 - /// Ok(()) 67 - /// } 68 - /// Err(e) => Err(e), 69 - /// } 54 + /// )?; 55 + /// Ok(()) 70 56 /// } 71 57 /// ``` 72 58 #[track_caller] ··· 103 101 // `fsleep()` could be a busy-wait loop so we always call `cpu_relax()`. 104 102 cpu_relax(); 105 103 } 104 + } 105 + 106 + /// Polls periodically until a condition is met, an error occurs, 107 + /// or the attempt limit is reached. 108 + /// 109 + /// The function repeatedly executes the given operation `op` closure and 110 + /// checks its result using the condition closure `cond`. 111 + /// 112 + /// If `cond` returns `true`, the function returns successfully with the result of `op`. 113 + /// Otherwise, it performs a busy wait for a duration specified by `delay_delta` 114 + /// before executing `op` again. 115 + /// 116 + /// This process continues until either `op` returns an error, `cond` 117 + /// returns `true`, or the attempt limit specified by `retry` is reached. 118 + /// 119 + /// # Errors 120 + /// 121 + /// If `op` returns an error, then that error is returned directly. 122 + /// 123 + /// If the attempt limit specified by `retry` is reached, then 124 + /// `Err(ETIMEDOUT)` is returned. 125 + /// 126 + /// # Examples 127 + /// 128 + /// ```no_run 129 + /// use kernel::io::{poll::read_poll_timeout_atomic, Io}; 130 + /// use kernel::time::Delta; 131 + /// 132 + /// const HW_READY: u16 = 0x01; 133 + /// 134 + /// fn wait_for_hardware<const SIZE: usize>(io: &Io<SIZE>) -> Result { 135 + /// read_poll_timeout_atomic( 136 + /// // The `op` closure reads the value of a specific status register. 137 + /// || io.try_read16(0x1000), 138 + /// // The `cond` closure takes a reference to the value returned by `op` 139 + /// // and checks whether the hardware is ready. 140 + /// |val: &u16| *val == HW_READY, 141 + /// Delta::from_micros(50), 142 + /// 1000, 143 + /// )?; 144 + /// Ok(()) 145 + /// } 146 + /// ``` 147 + pub fn read_poll_timeout_atomic<Op, Cond, T>( 148 + mut op: Op, 149 + mut cond: Cond, 150 + delay_delta: Delta, 151 + retry: usize, 152 + ) -> Result<T> 153 + where 154 + Op: FnMut() -> Result<T>, 155 + Cond: FnMut(&T) -> bool, 156 + { 157 + for _ in 0..retry { 158 + let val = op()?; 159 + if cond(&val) { 160 + return Ok(val); 161 + } 162 + 163 + if !delay_delta.is_zero() { 164 + udelay(delay_delta); 165 + } 166 + 167 + cpu_relax(); 168 + } 169 + 170 + Err(ETIMEDOUT) 106 171 }
+15 -12
rust/kernel/io/resource.rs
··· 5 5 //! 6 6 //! C header: [`include/linux/ioport.h`](srctree/include/linux/ioport.h) 7 7 8 - use core::ops::Deref; 9 - use core::ptr::NonNull; 8 + use core::{ 9 + ops::Deref, 10 + ptr::NonNull, // 11 + }; 10 12 11 - use crate::prelude::*; 12 - use crate::str::{CStr, CString}; 13 - use crate::types::Opaque; 13 + use crate::{ 14 + prelude::*, 15 + str::CString, 16 + types::Opaque, // 17 + }; 14 18 15 - /// Resource Size type. 16 - /// 17 - /// This is a type alias to either `u32` or `u64` depending on the config option 18 - /// `CONFIG_PHYS_ADDR_T_64BIT`, and it can be a u64 even on 32-bit architectures. 19 - pub type ResourceSize = bindings::phys_addr_t; 19 + pub use super::{ 20 + PhysAddr, 21 + ResourceSize, // 22 + }; 20 23 21 24 /// A region allocated from a parent [`Resource`]. 22 25 /// ··· 100 97 /// the region, or a part of it, is already in use. 101 98 pub fn request_region( 102 99 &self, 103 - start: ResourceSize, 100 + start: PhysAddr, 104 101 size: ResourceSize, 105 102 name: CString, 106 103 flags: Flags, ··· 134 131 } 135 132 136 133 /// Returns the start address of the resource. 137 - pub fn start(&self) -> ResourceSize { 134 + pub fn start(&self) -> PhysAddr { 138 135 let inner = self.0.get(); 139 136 // SAFETY: Safe as per the invariants of `Resource`. 140 137 unsafe { (*inner).start }
+2
rust/kernel/lib.rs
··· 97 97 pub mod firmware; 98 98 pub mod fmt; 99 99 pub mod fs; 100 + #[cfg(CONFIG_I2C = "y")] 101 + pub mod i2c; 100 102 pub mod id_pool; 101 103 pub mod init; 102 104 pub mod io;
+44 -187
rust/kernel/pci.rs
··· 5 5 //! C header: [`include/linux/pci.h`](srctree/include/linux/pci.h) 6 6 7 7 use crate::{ 8 - bindings, container_of, device, 9 - device_id::{RawDeviceId, RawDeviceIdIndex}, 10 - devres::Devres, 8 + bindings, 9 + container_of, 10 + device, 11 + device_id::{ 12 + RawDeviceId, 13 + RawDeviceIdIndex, // 14 + }, 11 15 driver, 12 - error::{from_result, to_result, Result}, 13 - io::{Io, IoRaw}, 14 - irq::{self, IrqRequest}, 16 + error::{ 17 + from_result, 18 + to_result, // 19 + }, 20 + prelude::*, 15 21 str::CStr, 16 - sync::aref::ARef, 17 22 types::Opaque, 18 - ThisModule, 23 + ThisModule, // 19 24 }; 20 25 use core::{ 21 26 marker::PhantomData, 22 - ops::Deref, 23 - ptr::{addr_of_mut, NonNull}, 27 + mem::offset_of, 28 + ptr::{ 29 + addr_of_mut, 30 + NonNull, // 31 + }, 24 32 }; 25 - use kernel::prelude::*; 26 33 27 34 mod id; 35 + mod io; 36 + mod irq; 28 37 29 - pub use self::id::{Class, ClassMask, Vendor}; 38 + pub use self::id::{ 39 + Class, 40 + ClassMask, 41 + Vendor, // 42 + }; 43 + pub use self::io::Bar; 44 + pub use self::irq::{ 45 + IrqType, 46 + IrqTypes, 47 + IrqVector, // 48 + }; 30 49 31 50 /// An adapter for the registration of PCI drivers. 32 51 pub struct Adapter<T: Driver>(T); ··· 97 78 let info = T::ID_TABLE.info(id.index()); 98 79 99 80 from_result(|| { 100 - let data = T::probe(pdev, info)?; 81 + let data = T::probe(pdev, info); 101 82 102 - pdev.as_ref().set_drvdata(data); 83 + pdev.as_ref().set_drvdata(data)?; 103 84 Ok(0) 104 85 }) 105 86 } ··· 114 95 // SAFETY: `remove_callback` is only ever called after a successful call to 115 96 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 116 97 // and stored a `Pin<KBox<T>>`. 117 - let data = unsafe { pdev.as_ref().drvdata_obtain::<Pin<KBox<T>>>() }; 98 + let data = unsafe { pdev.as_ref().drvdata_obtain::<T>() }; 118 99 119 100 T::unbind(pdev, data.as_ref()); 120 101 } ··· 268 249 /// fn probe( 269 250 /// _pdev: &pci::Device<Core>, 270 251 /// _id_info: &Self::IdInfo, 271 - /// ) -> Result<Pin<KBox<Self>>> { 252 + /// ) -> impl PinInit<Self, Error> { 272 253 /// Err(ENODEV) 273 254 /// } 274 255 /// } ··· 291 272 /// 292 273 /// Called when a new pci device is added or discovered. Implementers should 293 274 /// attempt to initialize the device here. 294 - fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 275 + fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> impl PinInit<Self, Error>; 295 276 296 277 /// PCI driver unbind. 297 278 /// ··· 323 304 Opaque<bindings::pci_dev>, 324 305 PhantomData<Ctx>, 325 306 ); 326 - 327 - /// A PCI BAR to perform I/O-Operations on. 328 - /// 329 - /// # Invariants 330 - /// 331 - /// `Bar` always holds an `IoRaw` inststance that holds a valid pointer to the start of the I/O 332 - /// memory mapped PCI bar and its size. 333 - pub struct Bar<const SIZE: usize = 0> { 334 - pdev: ARef<Device>, 335 - io: IoRaw<SIZE>, 336 - num: i32, 337 - } 338 - 339 - impl<const SIZE: usize> Bar<SIZE> { 340 - fn new(pdev: &Device, num: u32, name: &CStr) -> Result<Self> { 341 - let len = pdev.resource_len(num)?; 342 - if len == 0 { 343 - return Err(ENOMEM); 344 - } 345 - 346 - // Convert to `i32`, since that's what all the C bindings use. 347 - let num = i32::try_from(num)?; 348 - 349 - // SAFETY: 350 - // `pdev` is valid by the invariants of `Device`. 351 - // `num` is checked for validity by a previous call to `Device::resource_len`. 352 - // `name` is always valid. 353 - let ret = unsafe { bindings::pci_request_region(pdev.as_raw(), num, name.as_char_ptr()) }; 354 - if ret != 0 { 355 - return Err(EBUSY); 356 - } 357 - 358 - // SAFETY: 359 - // `pdev` is valid by the invariants of `Device`. 360 - // `num` is checked for validity by a previous call to `Device::resource_len`. 361 - // `name` is always valid. 362 - let ioptr: usize = unsafe { bindings::pci_iomap(pdev.as_raw(), num, 0) } as usize; 363 - if ioptr == 0 { 364 - // SAFETY: 365 - // `pdev` valid by the invariants of `Device`. 366 - // `num` is checked for validity by a previous call to `Device::resource_len`. 367 - unsafe { bindings::pci_release_region(pdev.as_raw(), num) }; 368 - return Err(ENOMEM); 369 - } 370 - 371 - let io = match IoRaw::new(ioptr, len as usize) { 372 - Ok(io) => io, 373 - Err(err) => { 374 - // SAFETY: 375 - // `pdev` is valid by the invariants of `Device`. 376 - // `ioptr` is guaranteed to be the start of a valid I/O mapped memory region. 377 - // `num` is checked for validity by a previous call to `Device::resource_len`. 378 - unsafe { Self::do_release(pdev, ioptr, num) }; 379 - return Err(err); 380 - } 381 - }; 382 - 383 - Ok(Bar { 384 - pdev: pdev.into(), 385 - io, 386 - num, 387 - }) 388 - } 389 - 390 - /// # Safety 391 - /// 392 - /// `ioptr` must be a valid pointer to the memory mapped PCI bar number `num`. 393 - unsafe fn do_release(pdev: &Device, ioptr: usize, num: i32) { 394 - // SAFETY: 395 - // `pdev` is valid by the invariants of `Device`. 396 - // `ioptr` is valid by the safety requirements. 397 - // `num` is valid by the safety requirements. 398 - unsafe { 399 - bindings::pci_iounmap(pdev.as_raw(), ioptr as *mut c_void); 400 - bindings::pci_release_region(pdev.as_raw(), num); 401 - } 402 - } 403 - 404 - fn release(&self) { 405 - // SAFETY: The safety requirements are guaranteed by the type invariant of `self.pdev`. 406 - unsafe { Self::do_release(&self.pdev, self.io.addr(), self.num) }; 407 - } 408 - } 409 - 410 - impl Bar { 411 - #[inline] 412 - fn index_is_valid(index: u32) -> bool { 413 - // A `struct pci_dev` owns an array of resources with at most `PCI_NUM_RESOURCES` entries. 414 - index < bindings::PCI_NUM_RESOURCES 415 - } 416 - } 417 - 418 - impl<const SIZE: usize> Drop for Bar<SIZE> { 419 - fn drop(&mut self) { 420 - self.release(); 421 - } 422 - } 423 - 424 - impl<const SIZE: usize> Deref for Bar<SIZE> { 425 - type Target = Io<SIZE>; 426 - 427 - fn deref(&self) -> &Self::Target { 428 - // SAFETY: By the type invariant of `Self`, the MMIO range in `self.io` is properly mapped. 429 - unsafe { Io::from_raw(&self.io) } 430 - } 431 - } 432 307 433 308 impl<Ctx: device::DeviceContext> Device<Ctx> { 434 309 #[inline] ··· 397 484 unsafe { (*self.as_raw()).subsystem_device } 398 485 } 399 486 400 - /// Returns the start of the given PCI bar resource. 487 + /// Returns the start of the given PCI BAR resource. 401 488 pub fn resource_start(&self, bar: u32) -> Result<bindings::resource_size_t> { 402 489 if !Bar::index_is_valid(bar) { 403 490 return Err(EINVAL); ··· 409 496 Ok(unsafe { bindings::pci_resource_start(self.as_raw(), bar.try_into()?) }) 410 497 } 411 498 412 - /// Returns the size of the given PCI bar resource. 499 + /// Returns the size of the given PCI BAR resource. 413 500 pub fn resource_len(&self, bar: u32) -> Result<bindings::resource_size_t> { 414 501 if !Bar::index_is_valid(bar) { 415 502 return Err(EINVAL); ··· 429 516 } 430 517 } 431 518 432 - impl Device<device::Bound> { 433 - /// Mapps an entire PCI-BAR after performing a region-request on it. I/O operation bound checks 434 - /// can be performed on compile time for offsets (plus the requested type size) < SIZE. 435 - pub fn iomap_region_sized<'a, const SIZE: usize>( 436 - &'a self, 437 - bar: u32, 438 - name: &'a CStr, 439 - ) -> impl PinInit<Devres<Bar<SIZE>>, Error> + 'a { 440 - Devres::new(self.as_ref(), Bar::<SIZE>::new(self, bar, name)) 441 - } 442 - 443 - /// Mapps an entire PCI-BAR after performing a region-request on it. 444 - pub fn iomap_region<'a>( 445 - &'a self, 446 - bar: u32, 447 - name: &'a CStr, 448 - ) -> impl PinInit<Devres<Bar>, Error> + 'a { 449 - self.iomap_region_sized::<0>(bar, name) 450 - } 451 - 452 - /// Returns an [`IrqRequest`] for the IRQ vector at the given index, if any. 453 - pub fn irq_vector(&self, index: u32) -> Result<IrqRequest<'_>> { 454 - // SAFETY: `self.as_raw` returns a valid pointer to a `struct pci_dev`. 455 - let irq = unsafe { crate::bindings::pci_irq_vector(self.as_raw(), index) }; 456 - if irq < 0 { 457 - return Err(crate::error::Error::from_errno(irq)); 458 - } 459 - // SAFETY: `irq` is guaranteed to be a valid IRQ number for `&self`. 460 - Ok(unsafe { IrqRequest::new(self.as_ref(), irq as u32) }) 461 - } 462 - 463 - /// Returns a [`kernel::irq::Registration`] for the IRQ vector at the given 464 - /// index. 465 - pub fn request_irq<'a, T: crate::irq::Handler + 'static>( 466 - &'a self, 467 - index: u32, 468 - flags: irq::Flags, 469 - name: &'static CStr, 470 - handler: impl PinInit<T, Error> + 'a, 471 - ) -> Result<impl PinInit<irq::Registration<T>, Error> + 'a> { 472 - let request = self.irq_vector(index)?; 473 - 474 - Ok(irq::Registration::<T>::new(request, flags, name, handler)) 475 - } 476 - 477 - /// Returns a [`kernel::irq::ThreadedRegistration`] for the IRQ vector at 478 - /// the given index. 479 - pub fn request_threaded_irq<'a, T: crate::irq::ThreadedHandler + 'static>( 480 - &'a self, 481 - index: u32, 482 - flags: irq::Flags, 483 - name: &'static CStr, 484 - handler: impl PinInit<T, Error> + 'a, 485 - ) -> Result<impl PinInit<irq::ThreadedRegistration<T>, Error> + 'a> { 486 - let request = self.irq_vector(index)?; 487 - 488 - Ok(irq::ThreadedRegistration::<T>::new( 489 - request, flags, name, handler, 490 - )) 491 - } 492 - } 493 - 494 519 impl Device<device::Core> { 495 520 /// Enable memory resources for this device. 496 521 pub fn enable_device_mem(&self) -> Result { ··· 442 591 // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. 443 592 unsafe { bindings::pci_set_master(self.as_raw()) }; 444 593 } 594 + } 595 + 596 + // SAFETY: `pci::Device` is a transparent wrapper of `struct pci_dev`. 597 + // The offset is guaranteed to point to a valid device field inside `pci::Device`. 598 + unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx> { 599 + const OFFSET: usize = offset_of!(bindings::pci_dev, dev); 445 600 } 446 601 447 602 // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
+5 -1
rust/kernel/pci/id.rs
··· 4 4 //! 5 5 //! This module contains PCI class codes, Vendor IDs, and supporting types. 6 6 7 - use crate::{bindings, error::code::EINVAL, error::Error, fmt, prelude::*}; 7 + use crate::{ 8 + bindings, 9 + fmt, 10 + prelude::*, // 11 + }; 8 12 9 13 /// PCI device class codes. 10 14 ///
+144
rust/kernel/pci/io.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! PCI memory-mapped I/O infrastructure. 4 + 5 + use super::Device; 6 + use crate::{ 7 + bindings, 8 + device, 9 + devres::Devres, 10 + io::{ 11 + Io, 12 + IoRaw, // 13 + }, 14 + prelude::*, 15 + sync::aref::ARef, // 16 + }; 17 + use core::ops::Deref; 18 + 19 + /// A PCI BAR to perform I/O-Operations on. 20 + /// 21 + /// # Invariants 22 + /// 23 + /// `Bar` always holds an `IoRaw` inststance that holds a valid pointer to the start of the I/O 24 + /// memory mapped PCI BAR and its size. 25 + pub struct Bar<const SIZE: usize = 0> { 26 + pdev: ARef<Device>, 27 + io: IoRaw<SIZE>, 28 + num: i32, 29 + } 30 + 31 + impl<const SIZE: usize> Bar<SIZE> { 32 + pub(super) fn new(pdev: &Device, num: u32, name: &CStr) -> Result<Self> { 33 + let len = pdev.resource_len(num)?; 34 + if len == 0 { 35 + return Err(ENOMEM); 36 + } 37 + 38 + // Convert to `i32`, since that's what all the C bindings use. 39 + let num = i32::try_from(num)?; 40 + 41 + // SAFETY: 42 + // `pdev` is valid by the invariants of `Device`. 43 + // `num` is checked for validity by a previous call to `Device::resource_len`. 44 + // `name` is always valid. 45 + let ret = unsafe { bindings::pci_request_region(pdev.as_raw(), num, name.as_char_ptr()) }; 46 + if ret != 0 { 47 + return Err(EBUSY); 48 + } 49 + 50 + // SAFETY: 51 + // `pdev` is valid by the invariants of `Device`. 52 + // `num` is checked for validity by a previous call to `Device::resource_len`. 53 + // `name` is always valid. 54 + let ioptr: usize = unsafe { bindings::pci_iomap(pdev.as_raw(), num, 0) } as usize; 55 + if ioptr == 0 { 56 + // SAFETY: 57 + // `pdev` valid by the invariants of `Device`. 58 + // `num` is checked for validity by a previous call to `Device::resource_len`. 59 + unsafe { bindings::pci_release_region(pdev.as_raw(), num) }; 60 + return Err(ENOMEM); 61 + } 62 + 63 + let io = match IoRaw::new(ioptr, len as usize) { 64 + Ok(io) => io, 65 + Err(err) => { 66 + // SAFETY: 67 + // `pdev` is valid by the invariants of `Device`. 68 + // `ioptr` is guaranteed to be the start of a valid I/O mapped memory region. 69 + // `num` is checked for validity by a previous call to `Device::resource_len`. 70 + unsafe { Self::do_release(pdev, ioptr, num) }; 71 + return Err(err); 72 + } 73 + }; 74 + 75 + Ok(Bar { 76 + pdev: pdev.into(), 77 + io, 78 + num, 79 + }) 80 + } 81 + 82 + /// # Safety 83 + /// 84 + /// `ioptr` must be a valid pointer to the memory mapped PCI BAR number `num`. 85 + unsafe fn do_release(pdev: &Device, ioptr: usize, num: i32) { 86 + // SAFETY: 87 + // `pdev` is valid by the invariants of `Device`. 88 + // `ioptr` is valid by the safety requirements. 89 + // `num` is valid by the safety requirements. 90 + unsafe { 91 + bindings::pci_iounmap(pdev.as_raw(), ioptr as *mut c_void); 92 + bindings::pci_release_region(pdev.as_raw(), num); 93 + } 94 + } 95 + 96 + fn release(&self) { 97 + // SAFETY: The safety requirements are guaranteed by the type invariant of `self.pdev`. 98 + unsafe { Self::do_release(&self.pdev, self.io.addr(), self.num) }; 99 + } 100 + } 101 + 102 + impl Bar { 103 + #[inline] 104 + pub(super) fn index_is_valid(index: u32) -> bool { 105 + // A `struct pci_dev` owns an array of resources with at most `PCI_NUM_RESOURCES` entries. 106 + index < bindings::PCI_NUM_RESOURCES 107 + } 108 + } 109 + 110 + impl<const SIZE: usize> Drop for Bar<SIZE> { 111 + fn drop(&mut self) { 112 + self.release(); 113 + } 114 + } 115 + 116 + impl<const SIZE: usize> Deref for Bar<SIZE> { 117 + type Target = Io<SIZE>; 118 + 119 + fn deref(&self) -> &Self::Target { 120 + // SAFETY: By the type invariant of `Self`, the MMIO range in `self.io` is properly mapped. 121 + unsafe { Io::from_raw(&self.io) } 122 + } 123 + } 124 + 125 + impl Device<device::Bound> { 126 + /// Maps an entire PCI BAR after performing a region-request on it. I/O operation bound checks 127 + /// can be performed on compile time for offsets (plus the requested type size) < SIZE. 128 + pub fn iomap_region_sized<'a, const SIZE: usize>( 129 + &'a self, 130 + bar: u32, 131 + name: &'a CStr, 132 + ) -> impl PinInit<Devres<Bar<SIZE>>, Error> + 'a { 133 + Devres::new(self.as_ref(), Bar::<SIZE>::new(self, bar, name)) 134 + } 135 + 136 + /// Maps an entire PCI BAR after performing a region-request on it. 137 + pub fn iomap_region<'a>( 138 + &'a self, 139 + bar: u32, 140 + name: &'a CStr, 141 + ) -> impl PinInit<Devres<Bar>, Error> + 'a { 142 + self.iomap_region_sized::<0>(bar, name) 143 + } 144 + }
+252
rust/kernel/pci/irq.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! PCI interrupt infrastructure. 4 + 5 + use super::Device; 6 + use crate::{ 7 + bindings, 8 + device, 9 + device::Bound, 10 + devres, 11 + error::to_result, 12 + irq::{ 13 + self, 14 + IrqRequest, // 15 + }, 16 + prelude::*, 17 + str::CStr, 18 + sync::aref::ARef, // 19 + }; 20 + use core::ops::RangeInclusive; 21 + 22 + /// IRQ type flags for PCI interrupt allocation. 23 + #[derive(Debug, Clone, Copy)] 24 + pub enum IrqType { 25 + /// INTx interrupts. 26 + Intx, 27 + /// Message Signaled Interrupts (MSI). 28 + Msi, 29 + /// Extended Message Signaled Interrupts (MSI-X). 30 + MsiX, 31 + } 32 + 33 + impl IrqType { 34 + /// Convert to the corresponding kernel flags. 35 + const fn as_raw(self) -> u32 { 36 + match self { 37 + IrqType::Intx => bindings::PCI_IRQ_INTX, 38 + IrqType::Msi => bindings::PCI_IRQ_MSI, 39 + IrqType::MsiX => bindings::PCI_IRQ_MSIX, 40 + } 41 + } 42 + } 43 + 44 + /// Set of IRQ types that can be used for PCI interrupt allocation. 45 + #[derive(Debug, Clone, Copy, Default)] 46 + pub struct IrqTypes(u32); 47 + 48 + impl IrqTypes { 49 + /// Create a set containing all IRQ types (MSI-X, MSI, and INTx). 50 + pub const fn all() -> Self { 51 + Self(bindings::PCI_IRQ_ALL_TYPES) 52 + } 53 + 54 + /// Build a set of IRQ types. 55 + /// 56 + /// # Examples 57 + /// 58 + /// ```ignore 59 + /// // Create a set with only MSI and MSI-X (no INTx interrupts). 60 + /// let msi_only = IrqTypes::default() 61 + /// .with(IrqType::Msi) 62 + /// .with(IrqType::MsiX); 63 + /// ``` 64 + pub const fn with(self, irq_type: IrqType) -> Self { 65 + Self(self.0 | irq_type.as_raw()) 66 + } 67 + 68 + /// Get the raw flags value. 69 + const fn as_raw(self) -> u32 { 70 + self.0 71 + } 72 + } 73 + 74 + /// Represents an allocated IRQ vector for a specific PCI device. 75 + /// 76 + /// This type ties an IRQ vector to the device it was allocated for, 77 + /// ensuring the vector is only used with the correct device. 78 + #[derive(Clone, Copy)] 79 + pub struct IrqVector<'a> { 80 + dev: &'a Device<Bound>, 81 + index: u32, 82 + } 83 + 84 + impl<'a> IrqVector<'a> { 85 + /// Creates a new [`IrqVector`] for the given device and index. 86 + /// 87 + /// # Safety 88 + /// 89 + /// - `index` must be a valid IRQ vector index for `dev`. 90 + /// - `dev` must point to a [`Device`] that has successfully allocated IRQ vectors. 91 + unsafe fn new(dev: &'a Device<Bound>, index: u32) -> Self { 92 + Self { dev, index } 93 + } 94 + 95 + /// Returns the raw vector index. 96 + fn index(&self) -> u32 { 97 + self.index 98 + } 99 + } 100 + 101 + impl<'a> TryInto<IrqRequest<'a>> for IrqVector<'a> { 102 + type Error = Error; 103 + 104 + fn try_into(self) -> Result<IrqRequest<'a>> { 105 + // SAFETY: `self.as_raw` returns a valid pointer to a `struct pci_dev`. 106 + let irq = unsafe { bindings::pci_irq_vector(self.dev.as_raw(), self.index()) }; 107 + if irq < 0 { 108 + return Err(crate::error::Error::from_errno(irq)); 109 + } 110 + // SAFETY: `irq` is guaranteed to be a valid IRQ number for `&self`. 111 + Ok(unsafe { IrqRequest::new(self.dev.as_ref(), irq as u32) }) 112 + } 113 + } 114 + 115 + /// Represents an IRQ vector allocation for a PCI device. 116 + /// 117 + /// This type ensures that IRQ vectors are properly allocated and freed by 118 + /// tying the allocation to the lifetime of this registration object. 119 + /// 120 + /// # Invariants 121 + /// 122 + /// The [`Device`] has successfully allocated IRQ vectors. 123 + struct IrqVectorRegistration { 124 + dev: ARef<Device>, 125 + } 126 + 127 + impl IrqVectorRegistration { 128 + /// Allocate and register IRQ vectors for the given PCI device. 129 + /// 130 + /// Allocates IRQ vectors and registers them with devres for automatic cleanup. 131 + /// Returns a range of valid IRQ vectors. 132 + fn register<'a>( 133 + dev: &'a Device<Bound>, 134 + min_vecs: u32, 135 + max_vecs: u32, 136 + irq_types: IrqTypes, 137 + ) -> Result<RangeInclusive<IrqVector<'a>>> { 138 + // SAFETY: 139 + // - `dev.as_raw()` is guaranteed to be a valid pointer to a `struct pci_dev` 140 + // by the type invariant of `Device`. 141 + // - `pci_alloc_irq_vectors` internally validates all other parameters 142 + // and returns error codes. 143 + let ret = unsafe { 144 + bindings::pci_alloc_irq_vectors(dev.as_raw(), min_vecs, max_vecs, irq_types.as_raw()) 145 + }; 146 + 147 + to_result(ret)?; 148 + let count = ret as u32; 149 + 150 + // SAFETY: 151 + // - `pci_alloc_irq_vectors` returns the number of allocated vectors on success. 152 + // - Vectors are 0-based, so valid indices are [0, count-1]. 153 + // - `pci_alloc_irq_vectors` guarantees `count >= min_vecs > 0`, so both `0` and 154 + // `count - 1` are valid IRQ vector indices for `dev`. 155 + let range = unsafe { IrqVector::new(dev, 0)..=IrqVector::new(dev, count - 1) }; 156 + 157 + // INVARIANT: The IRQ vector allocation for `dev` above was successful. 158 + let irq_vecs = Self { dev: dev.into() }; 159 + devres::register(dev.as_ref(), irq_vecs, GFP_KERNEL)?; 160 + 161 + Ok(range) 162 + } 163 + } 164 + 165 + impl Drop for IrqVectorRegistration { 166 + fn drop(&mut self) { 167 + // SAFETY: 168 + // - By the type invariant, `self.dev.as_raw()` is a valid pointer to a `struct pci_dev`. 169 + // - `self.dev` has successfully allocated IRQ vectors. 170 + unsafe { bindings::pci_free_irq_vectors(self.dev.as_raw()) }; 171 + } 172 + } 173 + 174 + impl Device<device::Bound> { 175 + /// Returns a [`kernel::irq::Registration`] for the given IRQ vector. 176 + pub fn request_irq<'a, T: crate::irq::Handler + 'static>( 177 + &'a self, 178 + vector: IrqVector<'a>, 179 + flags: irq::Flags, 180 + name: &'static CStr, 181 + handler: impl PinInit<T, Error> + 'a, 182 + ) -> impl PinInit<irq::Registration<T>, Error> + 'a { 183 + pin_init::pin_init_scope(move || { 184 + let request = vector.try_into()?; 185 + 186 + Ok(irq::Registration::<T>::new(request, flags, name, handler)) 187 + }) 188 + } 189 + 190 + /// Returns a [`kernel::irq::ThreadedRegistration`] for the given IRQ vector. 191 + pub fn request_threaded_irq<'a, T: crate::irq::ThreadedHandler + 'static>( 192 + &'a self, 193 + vector: IrqVector<'a>, 194 + flags: irq::Flags, 195 + name: &'static CStr, 196 + handler: impl PinInit<T, Error> + 'a, 197 + ) -> impl PinInit<irq::ThreadedRegistration<T>, Error> + 'a { 198 + pin_init::pin_init_scope(move || { 199 + let request = vector.try_into()?; 200 + 201 + Ok(irq::ThreadedRegistration::<T>::new( 202 + request, flags, name, handler, 203 + )) 204 + }) 205 + } 206 + 207 + /// Allocate IRQ vectors for this PCI device with automatic cleanup. 208 + /// 209 + /// Allocates between `min_vecs` and `max_vecs` interrupt vectors for the device. 210 + /// The allocation will use MSI-X, MSI, or INTx interrupts based on the `irq_types` 211 + /// parameter and hardware capabilities. When multiple types are specified, the kernel 212 + /// will try them in order of preference: MSI-X first, then MSI, then INTx interrupts. 213 + /// 214 + /// The allocated vectors are automatically freed when the device is unbound, using the 215 + /// devres (device resource management) system. 216 + /// 217 + /// # Arguments 218 + /// 219 + /// * `min_vecs` - Minimum number of vectors required. 220 + /// * `max_vecs` - Maximum number of vectors to allocate. 221 + /// * `irq_types` - Types of interrupts that can be used. 222 + /// 223 + /// # Returns 224 + /// 225 + /// Returns a range of IRQ vectors that were successfully allocated, or an error if the 226 + /// allocation fails or cannot meet the minimum requirement. 227 + /// 228 + /// # Examples 229 + /// 230 + /// ``` 231 + /// # use kernel::{ device::Bound, pci}; 232 + /// # fn no_run(dev: &pci::Device<Bound>) -> Result { 233 + /// // Allocate using any available interrupt type in the order mentioned above. 234 + /// let vectors = dev.alloc_irq_vectors(1, 32, pci::IrqTypes::all())?; 235 + /// 236 + /// // Allocate MSI or MSI-X only (no INTx interrupts). 237 + /// let msi_only = pci::IrqTypes::default() 238 + /// .with(pci::IrqType::Msi) 239 + /// .with(pci::IrqType::MsiX); 240 + /// let vectors = dev.alloc_irq_vectors(4, 16, msi_only)?; 241 + /// # Ok(()) 242 + /// # } 243 + /// ``` 244 + pub fn alloc_irq_vectors( 245 + &self, 246 + min_vecs: u32, 247 + max_vecs: u32, 248 + irq_types: IrqTypes, 249 + ) -> Result<RangeInclusive<IrqVector<'_>>> { 250 + IrqVectorRegistration::register(self, min_vecs, max_vecs, irq_types) 251 + } 252 + }
+36 -23
rust/kernel/platform.rs
··· 19 19 20 20 use core::{ 21 21 marker::PhantomData, 22 + mem::offset_of, 22 23 ptr::{addr_of_mut, NonNull}, 23 24 }; 24 25 ··· 75 74 let info = <Self as driver::Adapter>::id_info(pdev.as_ref()); 76 75 77 76 from_result(|| { 78 - let data = T::probe(pdev, info)?; 77 + let data = T::probe(pdev, info); 79 78 80 - pdev.as_ref().set_drvdata(data); 79 + pdev.as_ref().set_drvdata(data)?; 81 80 Ok(0) 82 81 }) 83 82 } ··· 92 91 // SAFETY: `remove_callback` is only ever called after a successful call to 93 92 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 94 93 // and stored a `Pin<KBox<T>>`. 95 - let data = unsafe { pdev.as_ref().drvdata_obtain::<Pin<KBox<T>>>() }; 94 + let data = unsafe { pdev.as_ref().drvdata_obtain::<T>() }; 96 95 97 96 T::unbind(pdev, data.as_ref()); 98 97 } ··· 167 166 /// fn probe( 168 167 /// _pdev: &platform::Device<Core>, 169 168 /// _id_info: Option<&Self::IdInfo>, 170 - /// ) -> Result<Pin<KBox<Self>>> { 169 + /// ) -> impl PinInit<Self, Error> { 171 170 /// Err(ENODEV) 172 171 /// } 173 172 /// } ··· 191 190 /// 192 191 /// Called when a new platform device is added or discovered. 193 192 /// Implementers should attempt to initialize the device here. 194 - fn probe(dev: &Device<device::Core>, id_info: Option<&Self::IdInfo>) 195 - -> Result<Pin<KBox<Self>>>; 193 + fn probe( 194 + dev: &Device<device::Core>, 195 + id_info: Option<&Self::IdInfo>, 196 + ) -> impl PinInit<Self, Error>; 196 197 197 198 /// Platform driver unbind. 198 199 /// ··· 288 285 } 289 286 } 290 287 288 + // SAFETY: `platform::Device` is a transparent wrapper of `struct platform_device`. 289 + // The offset is guaranteed to point to a valid device field inside `platform::Device`. 290 + unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx> { 291 + const OFFSET: usize = offset_of!(bindings::platform_device, dev); 292 + } 293 + 291 294 macro_rules! define_irq_accessor_by_index { 292 295 ( 293 296 $(#[$meta:meta])* $fn_name:ident, ··· 308 299 index: u32, 309 300 name: &'static CStr, 310 301 handler: impl PinInit<T, Error> + 'a, 311 - ) -> Result<impl PinInit<irq::$reg_type<T>, Error> + 'a> { 312 - let request = self.$request_fn(index)?; 302 + ) -> impl PinInit<irq::$reg_type<T>, Error> + 'a { 303 + pin_init::pin_init_scope(move || { 304 + let request = self.$request_fn(index)?; 313 305 314 - Ok(irq::$reg_type::<T>::new( 315 - request, 316 - flags, 317 - name, 318 - handler, 319 - )) 306 + Ok(irq::$reg_type::<T>::new( 307 + request, 308 + flags, 309 + name, 310 + handler, 311 + )) 312 + }) 320 313 } 321 314 }; 322 315 } ··· 334 323 pub fn $fn_name<'a, T: irq::$handler_trait + 'static>( 335 324 &'a self, 336 325 flags: irq::Flags, 337 - irq_name: &CStr, 326 + irq_name: &'a CStr, 338 327 name: &'static CStr, 339 328 handler: impl PinInit<T, Error> + 'a, 340 - ) -> Result<impl PinInit<irq::$reg_type<T>, Error> + 'a> { 341 - let request = self.$request_fn(irq_name)?; 329 + ) -> impl PinInit<irq::$reg_type<T>, Error> + 'a { 330 + pin_init::pin_init_scope(move || { 331 + let request = self.$request_fn(irq_name)?; 342 332 343 - Ok(irq::$reg_type::<T>::new( 344 - request, 345 - flags, 346 - name, 347 - handler, 348 - )) 333 + Ok(irq::$reg_type::<T>::new( 334 + request, 335 + flags, 336 + name, 337 + handler, 338 + )) 339 + }) 349 340 } 350 341 }; 351 342 }
+1 -1
rust/kernel/scatterlist.rs
··· 35 35 device::{Bound, Device}, 36 36 devres::Devres, 37 37 dma, error, 38 - io::resource::ResourceSize, 38 + io::ResourceSize, 39 39 page, 40 40 prelude::*, 41 41 types::{ARef, Opaque},
+37
rust/kernel/time/delay.rs
··· 47 47 bindings::fsleep(delta.as_micros_ceil() as c_ulong) 48 48 } 49 49 } 50 + 51 + /// Inserts a delay based on microseconds with busy waiting. 52 + /// 53 + /// Equivalent to the C side [`udelay()`], which delays in microseconds. 54 + /// 55 + /// `delta` must be within `[0, MAX_UDELAY_MS]` in milliseconds; 56 + /// otherwise, it is erroneous behavior. That is, it is considered a bug to 57 + /// call this function with an out-of-range value. 58 + /// 59 + /// The behavior above differs from the C side [`udelay()`] for which out-of-range 60 + /// values could lead to an overflow and unexpected behavior. 61 + /// 62 + /// [`udelay()`]: https://docs.kernel.org/timers/delay_sleep_functions.html#c.udelay 63 + pub fn udelay(delta: Delta) { 64 + const MAX_UDELAY_DELTA: Delta = Delta::from_millis(bindings::MAX_UDELAY_MS as i64); 65 + 66 + debug_assert!(delta.as_nanos() >= 0); 67 + debug_assert!(delta <= MAX_UDELAY_DELTA); 68 + 69 + let delta = if (Delta::ZERO..=MAX_UDELAY_DELTA).contains(&delta) { 70 + delta 71 + } else { 72 + MAX_UDELAY_DELTA 73 + }; 74 + 75 + // SAFETY: It is always safe to call `udelay()` with any duration. 76 + // Note that the kernel is compiled with `-fno-strict-overflow` 77 + // so any out-of-range value could lead to unexpected behavior 78 + // but won't lead to undefined behavior. 79 + unsafe { 80 + // Convert the duration to microseconds and round up to preserve 81 + // the guarantee; `udelay()` inserts a delay for at least 82 + // the provided duration, but that it may delay for longer 83 + // under some circumstances. 84 + bindings::udelay(delta.as_micros_ceil() as c_ulong) 85 + } 86 + }
+85
rust/kernel/uaccess.rs
··· 9 9 bindings, 10 10 error::Result, 11 11 ffi::{c_char, c_void}, 12 + fs::file, 12 13 prelude::*, 13 14 transmute::{AsBytes, FromBytes}, 14 15 }; ··· 288 287 self.read_raw(out) 289 288 } 290 289 290 + /// Reads raw data from the user slice into a kernel buffer partially. 291 + /// 292 + /// This is the same as [`Self::read_slice`] but considers the given `offset` into `out` and 293 + /// truncates the read to the boundaries of `self` and `out`. 294 + /// 295 + /// On success, returns the number of bytes read. 296 + pub fn read_slice_partial(&mut self, out: &mut [u8], offset: usize) -> Result<usize> { 297 + let end = offset.saturating_add(self.len()).min(out.len()); 298 + 299 + let Some(dst) = out.get_mut(offset..end) else { 300 + return Ok(0); 301 + }; 302 + 303 + self.read_slice(dst)?; 304 + Ok(dst.len()) 305 + } 306 + 307 + /// Reads raw data from the user slice into a kernel buffer partially. 308 + /// 309 + /// This is the same as [`Self::read_slice_partial`] but updates the given [`file::Offset`] by 310 + /// the number of bytes read. 311 + /// 312 + /// This is equivalent to C's `simple_write_to_buffer()`. 313 + /// 314 + /// On success, returns the number of bytes read. 315 + pub fn read_slice_file(&mut self, out: &mut [u8], offset: &mut file::Offset) -> Result<usize> { 316 + if offset.is_negative() { 317 + return Err(EINVAL); 318 + } 319 + 320 + let Ok(offset_index) = (*offset).try_into() else { 321 + return Ok(0); 322 + }; 323 + 324 + let read = self.read_slice_partial(out, offset_index)?; 325 + 326 + // OVERFLOW: `offset + read <= data.len() <= isize::MAX <= Offset::MAX` 327 + *offset += read as i64; 328 + 329 + Ok(read) 330 + } 331 + 291 332 /// Reads a value of the specified type. 292 333 /// 293 334 /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of ··· 479 436 self.ptr = self.ptr.wrapping_byte_add(len); 480 437 self.length -= len; 481 438 Ok(()) 439 + } 440 + 441 + /// Writes raw data to this user pointer from a kernel buffer partially. 442 + /// 443 + /// This is the same as [`Self::write_slice`] but considers the given `offset` into `data` and 444 + /// truncates the write to the boundaries of `self` and `data`. 445 + /// 446 + /// On success, returns the number of bytes written. 447 + pub fn write_slice_partial(&mut self, data: &[u8], offset: usize) -> Result<usize> { 448 + let end = offset.saturating_add(self.len()).min(data.len()); 449 + 450 + let Some(src) = data.get(offset..end) else { 451 + return Ok(0); 452 + }; 453 + 454 + self.write_slice(src)?; 455 + Ok(src.len()) 456 + } 457 + 458 + /// Writes raw data to this user pointer from a kernel buffer partially. 459 + /// 460 + /// This is the same as [`Self::write_slice_partial`] but updates the given [`file::Offset`] by 461 + /// the number of bytes written. 462 + /// 463 + /// This is equivalent to C's `simple_read_from_buffer()`. 464 + /// 465 + /// On success, returns the number of bytes written. 466 + pub fn write_slice_file(&mut self, data: &[u8], offset: &mut file::Offset) -> Result<usize> { 467 + if offset.is_negative() { 468 + return Err(EINVAL); 469 + } 470 + 471 + let Ok(offset_index) = (*offset).try_into() else { 472 + return Ok(0); 473 + }; 474 + 475 + let written = self.write_slice_partial(data, offset_index)?; 476 + 477 + // OVERFLOW: `offset + written <= data.len() <= isize::MAX <= Offset::MAX` 478 + *offset += written as i64; 479 + 480 + Ok(written) 482 481 } 483 482 484 483 /// Writes the provided Rust value to this userspace pointer.
+19 -6
rust/kernel/usb.rs
··· 15 15 types::{AlwaysRefCounted, Opaque}, 16 16 ThisModule, 17 17 }; 18 - use core::{marker::PhantomData, mem::MaybeUninit, ptr::NonNull}; 18 + use core::{ 19 + marker::PhantomData, 20 + mem::{ 21 + offset_of, 22 + MaybeUninit, // 23 + }, 24 + ptr::NonNull, 25 + }; 19 26 20 27 /// An adapter for the registration of USB drivers. 21 28 pub struct Adapter<T: Driver>(T); ··· 74 67 let id = unsafe { &*id.cast::<DeviceId>() }; 75 68 76 69 let info = T::ID_TABLE.info(id.index()); 77 - let data = T::probe(intf, id, info)?; 70 + let data = T::probe(intf, id, info); 78 71 79 72 let dev: &device::Device<device::CoreInternal> = intf.as_ref(); 80 - dev.set_drvdata(data); 73 + dev.set_drvdata(data)?; 81 74 Ok(0) 82 75 }) 83 76 } ··· 94 87 // SAFETY: `disconnect_callback` is only ever called after a successful call to 95 88 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 96 89 // and stored a `Pin<KBox<T>>`. 97 - let data = unsafe { dev.drvdata_obtain::<Pin<KBox<T>>>() }; 90 + let data = unsafe { dev.drvdata_obtain::<T>() }; 98 91 99 92 T::disconnect(intf, data.as_ref()); 100 93 } ··· 277 270 /// _interface: &usb::Interface<Core>, 278 271 /// _id: &usb::DeviceId, 279 272 /// _info: &Self::IdInfo, 280 - /// ) -> Result<Pin<KBox<Self>>> { 273 + /// ) -> impl PinInit<Self, Error> { 281 274 /// Err(ENODEV) 282 275 /// } 283 276 /// ··· 299 292 interface: &Interface<device::Core>, 300 293 id: &DeviceId, 301 294 id_info: &Self::IdInfo, 302 - ) -> Result<Pin<KBox<Self>>>; 295 + ) -> impl PinInit<Self, Error>; 303 296 304 297 /// USB driver disconnect. 305 298 /// ··· 329 322 fn as_raw(&self) -> *mut bindings::usb_interface { 330 323 self.0.get() 331 324 } 325 + } 326 + 327 + // SAFETY: `usb::Interface` is a transparent wrapper of `struct usb_interface`. 328 + // The offset is guaranteed to point to a valid device field inside `usb::Interface`. 329 + unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Interface<Ctx> { 330 + const OFFSET: usize = offset_of!(bindings::usb_interface, dev); 332 331 } 333 332 334 333 // SAFETY: `Interface` is a transparent wrapper of a type that doesn't depend on
+87
rust/pin-init/src/lib.rs
··· 1392 1392 unsafe { pin_init_from_closure(init) } 1393 1393 } 1394 1394 1395 + /// Construct an initializer in a closure and run it. 1396 + /// 1397 + /// Returns an initializer that first runs the closure and then the initializer returned by it. 1398 + /// 1399 + /// See also [`init_scope`]. 1400 + /// 1401 + /// # Examples 1402 + /// 1403 + /// ``` 1404 + /// # use pin_init::*; 1405 + /// # #[pin_data] 1406 + /// # struct Foo { a: u64, b: isize } 1407 + /// # struct Bar { a: u32, b: isize } 1408 + /// # fn lookup_bar() -> Result<Bar, Error> { todo!() } 1409 + /// # struct Error; 1410 + /// fn init_foo() -> impl PinInit<Foo, Error> { 1411 + /// pin_init_scope(|| { 1412 + /// let bar = lookup_bar()?; 1413 + /// Ok(try_pin_init!(Foo { a: bar.a.into(), b: bar.b }? Error)) 1414 + /// }) 1415 + /// } 1416 + /// ``` 1417 + /// 1418 + /// This initializer will first execute `lookup_bar()`, match on it, if it returned an error, the 1419 + /// initializer itself will fail with that error. If it returned `Ok`, then it will run the 1420 + /// initializer returned by the [`try_pin_init!`] invocation. 1421 + pub fn pin_init_scope<T, E, F, I>(make_init: F) -> impl PinInit<T, E> 1422 + where 1423 + F: FnOnce() -> Result<I, E>, 1424 + I: PinInit<T, E>, 1425 + { 1426 + // SAFETY: 1427 + // - If `make_init` returns `Err`, `Err` is returned and `slot` is completely uninitialized, 1428 + // - If `make_init` returns `Ok`, safety requirement are fulfilled by `init.__pinned_init`. 1429 + // - The safety requirements of `init.__pinned_init` are fulfilled, since it's being called 1430 + // from an initializer. 1431 + unsafe { 1432 + pin_init_from_closure(move |slot: *mut T| -> Result<(), E> { 1433 + let init = make_init()?; 1434 + init.__pinned_init(slot) 1435 + }) 1436 + } 1437 + } 1438 + 1439 + /// Construct an initializer in a closure and run it. 1440 + /// 1441 + /// Returns an initializer that first runs the closure and then the initializer returned by it. 1442 + /// 1443 + /// See also [`pin_init_scope`]. 1444 + /// 1445 + /// # Examples 1446 + /// 1447 + /// ``` 1448 + /// # use pin_init::*; 1449 + /// # struct Foo { a: u64, b: isize } 1450 + /// # struct Bar { a: u32, b: isize } 1451 + /// # fn lookup_bar() -> Result<Bar, Error> { todo!() } 1452 + /// # struct Error; 1453 + /// fn init_foo() -> impl Init<Foo, Error> { 1454 + /// init_scope(|| { 1455 + /// let bar = lookup_bar()?; 1456 + /// Ok(try_init!(Foo { a: bar.a.into(), b: bar.b }? Error)) 1457 + /// }) 1458 + /// } 1459 + /// ``` 1460 + /// 1461 + /// This initializer will first execute `lookup_bar()`, match on it, if it returned an error, the 1462 + /// initializer itself will fail with that error. If it returned `Ok`, then it will run the 1463 + /// initializer returned by the [`try_init!`] invocation. 1464 + pub fn init_scope<T, E, F, I>(make_init: F) -> impl Init<T, E> 1465 + where 1466 + F: FnOnce() -> Result<I, E>, 1467 + I: Init<T, E>, 1468 + { 1469 + // SAFETY: 1470 + // - If `make_init` returns `Err`, `Err` is returned and `slot` is completely uninitialized, 1471 + // - If `make_init` returns `Ok`, safety requirement are fulfilled by `init.__init`. 1472 + // - The safety requirements of `init.__init` are fulfilled, since it's being called from an 1473 + // initializer. 1474 + unsafe { 1475 + init_from_closure(move |slot: *mut T| -> Result<(), E> { 1476 + let init = make_init()?; 1477 + init.__init(slot) 1478 + }) 1479 + } 1480 + } 1481 + 1395 1482 // SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`. 1396 1483 unsafe impl<T> Init<T> for T { 1397 1484 unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> {
+30 -14
samples/kobject/kset-example.c
··· 37 37 /* a custom attribute that works just for a struct foo_obj. */ 38 38 struct foo_attribute { 39 39 struct attribute attr; 40 - ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf); 41 - ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count); 40 + ssize_t (*show)(struct foo_obj *foo, const struct foo_attribute *attr, char *buf); 41 + ssize_t (*store)(struct foo_obj *foo, const struct foo_attribute *attr, 42 + const char *buf, size_t count); 42 43 }; 43 - #define to_foo_attr(x) container_of(x, struct foo_attribute, attr) 44 + #define to_foo_attr(x) container_of_const(x, struct foo_attribute, attr) 44 45 45 46 /* 46 47 * The default show function that must be passed to sysfs. This will be ··· 54 53 struct attribute *attr, 55 54 char *buf) 56 55 { 57 - struct foo_attribute *attribute; 56 + const struct foo_attribute *attribute; 58 57 struct foo_obj *foo; 59 58 60 59 attribute = to_foo_attr(attr); ··· 74 73 struct attribute *attr, 75 74 const char *buf, size_t len) 76 75 { 77 - struct foo_attribute *attribute; 76 + const struct foo_attribute *attribute; 78 77 struct foo_obj *foo; 79 78 80 79 attribute = to_foo_attr(attr); ··· 110 109 /* 111 110 * The "foo" file where the .foo variable is read from and written to. 112 111 */ 113 - static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr, 112 + static ssize_t foo_show(struct foo_obj *foo_obj, const struct foo_attribute *attr, 114 113 char *buf) 115 114 { 116 115 return sysfs_emit(buf, "%d\n", foo_obj->foo); 117 116 } 118 117 119 - static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr, 118 + static ssize_t foo_store(struct foo_obj *foo_obj, const struct foo_attribute *attr, 120 119 const char *buf, size_t count) 121 120 { 122 121 int ret; ··· 129 128 } 130 129 131 130 /* Sysfs attributes cannot be world-writable. */ 132 - static struct foo_attribute foo_attribute = 131 + static const struct foo_attribute foo_attribute = 133 132 __ATTR(foo, 0664, foo_show, foo_store); 134 133 135 134 /* 136 135 * More complex function where we determine which variable is being accessed by 137 136 * looking at the attribute for the "baz" and "bar" files. 138 137 */ 139 - static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr, 138 + static ssize_t b_show(struct foo_obj *foo_obj, const struct foo_attribute *attr, 140 139 char *buf) 141 140 { 142 141 int var; ··· 148 147 return sysfs_emit(buf, "%d\n", var); 149 148 } 150 149 151 - static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr, 150 + static ssize_t b_store(struct foo_obj *foo_obj, const struct foo_attribute *attr, 152 151 const char *buf, size_t count) 153 152 { 154 153 int var, ret; ··· 164 163 return count; 165 164 } 166 165 167 - static struct foo_attribute baz_attribute = 166 + static const struct foo_attribute baz_attribute = 168 167 __ATTR(baz, 0664, b_show, b_store); 169 - static struct foo_attribute bar_attribute = 168 + static const struct foo_attribute bar_attribute = 170 169 __ATTR(bar, 0664, b_show, b_store); 171 170 172 171 /* 173 172 * Create a group of attributes so that we can create and destroy them all 174 173 * at once. 175 174 */ 176 - static struct attribute *foo_default_attrs[] = { 175 + static const struct attribute *const foo_default_attrs[] = { 177 176 &foo_attribute.attr, 178 177 &baz_attribute.attr, 179 178 &bar_attribute.attr, 180 179 NULL, /* need to NULL terminate the list of attributes */ 181 180 }; 182 - ATTRIBUTE_GROUPS(foo_default); 181 + 182 + static umode_t foo_default_attrs_is_visible(struct kobject *kobj, 183 + const struct attribute *attr, 184 + int n) 185 + { 186 + /* Hide attributes with the same name as the kobject. */ 187 + if (strcmp(kobject_name(kobj), attr->name) == 0) 188 + return 0; 189 + return attr->mode; 190 + } 191 + 192 + static const struct attribute_group foo_default_group = { 193 + .attrs_const = foo_default_attrs, 194 + .is_visible_const = foo_default_attrs_is_visible, 195 + }; 196 + __ATTRIBUTE_GROUPS(foo_default); 183 197 184 198 /* 185 199 * Our own ktype for our kobjects. Here we specify our sysfs ops, the
+24 -1
samples/rust/Kconfig
··· 84 84 85 85 If unsure, say N. 86 86 87 + config SAMPLE_RUST_DRIVER_I2C 88 + tristate "I2C Driver" 89 + depends on I2C=y 90 + help 91 + This option builds the Rust I2C driver sample. 92 + 93 + To compile this as a module, choose M here: 94 + the module will be called rust_driver_i2c. 95 + 96 + If unsure, say N. 97 + 98 + config SAMPLE_RUST_I2C_CLIENT 99 + tristate "I2C Client Registration" 100 + depends on I2C=y 101 + help 102 + This option builds the Rust I2C client manual creation 103 + sample. 104 + 105 + To compile this as a module, choose M here: 106 + the module will be called rust_i2c_client. 107 + 108 + If unsure, say N. 109 + 87 110 config SAMPLE_RUST_DRIVER_PCI 88 111 tristate "PCI Driver" 89 112 depends on PCI ··· 114 91 This option builds the Rust PCI driver sample. 115 92 116 93 To compile this as a module, choose M here: 117 - the module will be called driver_pci. 94 + the module will be called rust_driver_pci. 118 95 119 96 If unsure, say N. 120 97
+2
samples/rust/Makefile
··· 7 7 obj-$(CONFIG_SAMPLE_RUST_DEBUGFS) += rust_debugfs.o 8 8 obj-$(CONFIG_SAMPLE_RUST_DEBUGFS_SCOPED) += rust_debugfs_scoped.o 9 9 obj-$(CONFIG_SAMPLE_RUST_DMA) += rust_dma.o 10 + obj-$(CONFIG_SAMPLE_RUST_DRIVER_I2C) += rust_driver_i2c.o 11 + obj-$(CONFIG_SAMPLE_RUST_I2C_CLIENT) += rust_i2c_client.o 10 12 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o 11 13 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o 12 14 obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o
+24 -10
samples/rust/rust_debugfs.rs
··· 36 36 use kernel::debugfs::{Dir, File}; 37 37 use kernel::new_mutex; 38 38 use kernel::prelude::*; 39 + use kernel::sizes::*; 39 40 use kernel::sync::atomic::{Atomic, Relaxed}; 40 41 use kernel::sync::Mutex; 41 42 use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef}; ··· 61 60 counter: File<Atomic<usize>>, 62 61 #[pin] 63 62 inner: File<Mutex<Inner>>, 63 + #[pin] 64 + array_blob: File<Mutex<[u8; 4]>>, 65 + #[pin] 66 + vector_blob: File<Mutex<KVec<u8>>>, 64 67 } 65 68 66 69 #[derive(Debug)] ··· 109 104 fn probe( 110 105 pdev: &platform::Device<Core>, 111 106 _info: Option<&Self::IdInfo>, 112 - ) -> Result<Pin<KBox<Self>>> { 113 - let result = KBox::try_pin_init(RustDebugFs::new(pdev), GFP_KERNEL)?; 114 - // We can still mutate fields through the files which are atomic or mutexed: 115 - result.counter.store(91, Relaxed); 116 - { 117 - let mut guard = result.inner.lock(); 118 - guard.x = guard.y; 119 - guard.y = 42; 120 - } 121 - Ok(result) 107 + ) -> impl PinInit<Self, Error> { 108 + RustDebugFs::new(pdev).pin_chain(|this| { 109 + this.counter.store(91, Relaxed); 110 + { 111 + let mut guard = this.inner.lock(); 112 + guard.x = guard.y; 113 + guard.y = 42; 114 + } 115 + 116 + Ok(()) 117 + }) 122 118 } 123 119 } 124 120 ··· 147 141 ), 148 142 counter <- Self::build_counter(&debugfs), 149 143 inner <- Self::build_inner(&debugfs), 144 + array_blob <- debugfs.read_write_binary_file( 145 + c_str!("array_blob"), 146 + new_mutex!([0x62, 0x6c, 0x6f, 0x62]), 147 + ), 148 + vector_blob <- debugfs.read_write_binary_file( 149 + c_str!("vector_blob"), 150 + new_mutex!(kernel::kvec!(0x42; SZ_4K)?), 151 + ), 150 152 _debugfs: debugfs, 151 153 pdev: pdev.into(), 152 154 }
+10 -4
samples/rust/rust_debugfs_scoped.rs
··· 8 8 9 9 use kernel::debugfs::{Dir, Scope}; 10 10 use kernel::prelude::*; 11 + use kernel::sizes::*; 11 12 use kernel::sync::atomic::Atomic; 12 13 use kernel::sync::Mutex; 13 14 use kernel::{c_str, new_mutex, str::CString}; ··· 67 66 GFP_KERNEL, 68 67 )?; 69 68 } 69 + let blob = KBox::pin_init(new_mutex!([0x42; SZ_4K]), GFP_KERNEL)?; 70 70 71 71 let scope = KBox::pin_init( 72 - mod_data 73 - .device_dir 74 - .scope(DeviceData { name, nums }, &file_name, |dev_data, dir| { 72 + mod_data.device_dir.scope( 73 + DeviceData { name, nums, blob }, 74 + &file_name, 75 + |dev_data, dir| { 75 76 for (idx, val) in dev_data.nums.iter().enumerate() { 76 77 let Ok(name) = CString::try_from_fmt(fmt!("{idx}")) else { 77 78 return; 78 79 }; 79 80 dir.read_write_file(&name, val); 80 81 } 81 - }), 82 + dir.read_write_binary_file(c_str!("blob"), &dev_data.blob); 83 + }, 84 + ), 82 85 GFP_KERNEL, 83 86 )?; 84 87 (*mod_data.devices.lock()).push(scope, GFP_KERNEL)?; ··· 115 110 struct DeviceData { 116 111 name: CString, 117 112 nums: KVec<Atomic<usize>>, 113 + blob: Pin<KBox<Mutex<[u8; SZ_4K]>>>, 118 114 } 119 115 120 116 fn init_control(base_dir: &Dir, dyn_dirs: Dir) -> impl PinInit<Scope<ModuleData>> + '_ {
+17 -20
samples/rust/rust_dma.rs
··· 55 55 type IdInfo = (); 56 56 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 57 57 58 - fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 59 - dev_info!(pdev.as_ref(), "Probe DMA test driver.\n"); 58 + fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 59 + pin_init::pin_init_scope(move || { 60 + dev_info!(pdev.as_ref(), "Probe DMA test driver.\n"); 60 61 61 - let mask = DmaMask::new::<64>(); 62 + let mask = DmaMask::new::<64>(); 62 63 63 - // SAFETY: There are no concurrent calls to DMA allocation and mapping primitives. 64 - unsafe { pdev.dma_set_mask_and_coherent(mask)? }; 64 + // SAFETY: There are no concurrent calls to DMA allocation and mapping primitives. 65 + unsafe { pdev.dma_set_mask_and_coherent(mask)? }; 65 66 66 - let ca: CoherentAllocation<MyStruct> = 67 - CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; 67 + let ca: CoherentAllocation<MyStruct> = 68 + CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; 68 69 69 - for (i, value) in TEST_VALUES.into_iter().enumerate() { 70 - kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1))?; 71 - } 70 + for (i, value) in TEST_VALUES.into_iter().enumerate() { 71 + kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1))?; 72 + } 72 73 73 - let size = 4 * page::PAGE_SIZE; 74 - let pages = VVec::with_capacity(size, GFP_KERNEL)?; 74 + let size = 4 * page::PAGE_SIZE; 75 + let pages = VVec::with_capacity(size, GFP_KERNEL)?; 75 76 76 - let sgt = SGTable::new(pdev.as_ref(), pages, DataDirection::ToDevice, GFP_KERNEL); 77 + let sgt = SGTable::new(pdev.as_ref(), pages, DataDirection::ToDevice, GFP_KERNEL); 77 78 78 - let drvdata = KBox::pin_init( 79 - try_pin_init!(Self { 79 + Ok(try_pin_init!(Self { 80 80 pdev: pdev.into(), 81 81 ca, 82 82 sgt <- sgt, 83 - }), 84 - GFP_KERNEL, 85 - )?; 86 - 87 - Ok(drvdata) 83 + })) 84 + }) 88 85 } 89 86 } 90 87
+35 -24
samples/rust/rust_driver_auxiliary.rs
··· 5 5 //! To make this driver probe, QEMU must be run with `-device pci-testdev`. 6 6 7 7 use kernel::{ 8 - auxiliary, c_str, device::Core, driver, error::Error, pci, prelude::*, InPlaceModule, 8 + auxiliary, c_str, 9 + device::{Bound, Core}, 10 + devres::Devres, 11 + driver, 12 + error::Error, 13 + pci, 14 + prelude::*, 15 + InPlaceModule, 9 16 }; 10 17 18 + use core::any::TypeId; 11 19 use pin_init::PinInit; 12 20 13 21 const MODULE_NAME: &CStr = <LocalModule as kernel::ModuleMetadata>::NAME; ··· 35 27 36 28 const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE; 37 29 38 - fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 30 + fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 39 31 dev_info!( 40 32 adev.as_ref(), 41 33 "Probing auxiliary driver for auxiliary device with id={}\n", ··· 44 36 45 37 ParentDriver::connect(adev)?; 46 38 47 - let this = KBox::new(Self, GFP_KERNEL)?; 48 - 49 - Ok(this.into()) 39 + Ok(Self) 50 40 } 51 41 } 52 42 43 + #[pin_data] 53 44 struct ParentDriver { 54 - _reg: [auxiliary::Registration; 2], 45 + private: TypeId, 46 + #[pin] 47 + _reg0: Devres<auxiliary::Registration>, 48 + #[pin] 49 + _reg1: Devres<auxiliary::Registration>, 55 50 } 56 51 57 52 kernel::pci_device_table!( ··· 69 58 70 59 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 71 60 72 - fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 73 - let this = KBox::new( 74 - Self { 75 - _reg: [ 76 - auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME)?, 77 - auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME)?, 78 - ], 79 - }, 80 - GFP_KERNEL, 81 - )?; 82 - 83 - Ok(this.into()) 61 + fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> { 62 + try_pin_init!(Self { 63 + private: TypeId::of::<Self>(), 64 + _reg0 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 0, MODULE_NAME), 65 + _reg1 <- auxiliary::Registration::new(pdev.as_ref(), AUXILIARY_NAME, 1, MODULE_NAME), 66 + }) 84 67 } 85 68 } 86 69 87 70 impl ParentDriver { 88 - fn connect(adev: &auxiliary::Device) -> Result<()> { 89 - let parent = adev.parent().ok_or(EINVAL)?; 90 - let pdev: &pci::Device = parent.try_into()?; 71 + fn connect(adev: &auxiliary::Device<Bound>) -> Result { 72 + let dev = adev.parent(); 73 + let pdev: &pci::Device<Bound> = dev.try_into()?; 74 + let drvdata = dev.drvdata::<Self>()?; 91 75 92 - let vendor = pdev.vendor_id(); 93 76 dev_info!( 94 - adev.as_ref(), 77 + dev, 95 78 "Connect auxiliary {} with parent: VendorID={}, DeviceID={:#x}\n", 96 79 adev.id(), 97 - vendor, 80 + pdev.vendor_id(), 98 81 pdev.device_id() 82 + ); 83 + 84 + dev_info!( 85 + dev, 86 + "We have access to the private data of {:?}.\n", 87 + drvdata.private 99 88 ); 100 89 101 90 Ok(())
+74
samples/rust/rust_driver_i2c.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Rust I2C driver sample. 4 + 5 + use kernel::{ 6 + acpi, 7 + c_str, 8 + device::Core, 9 + i2c, 10 + of, 11 + prelude::*, // 12 + }; 13 + 14 + struct SampleDriver; 15 + 16 + kernel::acpi_device_table! { 17 + ACPI_TABLE, 18 + MODULE_ACPI_TABLE, 19 + <SampleDriver as i2c::Driver>::IdInfo, 20 + [(acpi::DeviceId::new(c_str!("LNUXBEEF")), 0)] 21 + } 22 + 23 + kernel::i2c_device_table! { 24 + I2C_TABLE, 25 + MODULE_I2C_TABLE, 26 + <SampleDriver as i2c::Driver>::IdInfo, 27 + [(i2c::DeviceId::new(c_str!("rust_driver_i2c")), 0)] 28 + } 29 + 30 + kernel::of_device_table! { 31 + OF_TABLE, 32 + MODULE_OF_TABLE, 33 + <SampleDriver as i2c::Driver>::IdInfo, 34 + [(of::DeviceId::new(c_str!("test,rust_driver_i2c")), 0)] 35 + } 36 + 37 + impl i2c::Driver for SampleDriver { 38 + type IdInfo = u32; 39 + 40 + const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); 41 + const I2C_ID_TABLE: Option<i2c::IdTable<Self::IdInfo>> = Some(&I2C_TABLE); 42 + const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); 43 + 44 + fn probe( 45 + idev: &i2c::I2cClient<Core>, 46 + info: Option<&Self::IdInfo>, 47 + ) -> impl PinInit<Self, Error> { 48 + let dev = idev.as_ref(); 49 + 50 + dev_info!(dev, "Probe Rust I2C driver sample.\n"); 51 + 52 + if let Some(info) = info { 53 + dev_info!(dev, "Probed with info: '{}'.\n", info); 54 + } 55 + 56 + Ok(Self) 57 + } 58 + 59 + fn shutdown(idev: &i2c::I2cClient<Core>, _this: Pin<&Self>) { 60 + dev_info!(idev.as_ref(), "Shutdown Rust I2C driver sample.\n"); 61 + } 62 + 63 + fn unbind(idev: &i2c::I2cClient<Core>, _this: Pin<&Self>) { 64 + dev_info!(idev.as_ref(), "Unbind Rust I2C driver sample.\n"); 65 + } 66 + } 67 + 68 + kernel::module_i2c_driver! { 69 + type: SampleDriver, 70 + name: "rust_driver_i2c", 71 + authors: ["Igor Korotin"], 72 + description: "Rust I2C driver", 73 + license: "GPL v2", 74 + }
+23 -24
samples/rust/rust_driver_pci.rs
··· 65 65 66 66 const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 67 67 68 - fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 69 - let vendor = pdev.vendor_id(); 70 - dev_dbg!( 71 - pdev.as_ref(), 72 - "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n", 73 - vendor, 74 - pdev.device_id() 75 - ); 68 + fn probe(pdev: &pci::Device<Core>, info: &Self::IdInfo) -> impl PinInit<Self, Error> { 69 + pin_init::pin_init_scope(move || { 70 + let vendor = pdev.vendor_id(); 71 + dev_dbg!( 72 + pdev.as_ref(), 73 + "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n", 74 + vendor, 75 + pdev.device_id() 76 + ); 76 77 77 - pdev.enable_device_mem()?; 78 - pdev.set_master(); 78 + pdev.enable_device_mem()?; 79 + pdev.set_master(); 79 80 80 - let drvdata = KBox::pin_init( 81 - try_pin_init!(Self { 81 + Ok(try_pin_init!(Self { 82 82 bar <- pdev.iomap_region_sized::<{ Regs::END }>(0, c_str!("rust_driver_pci")), 83 - pdev: pdev.into(), 84 83 index: *info, 85 - }), 86 - GFP_KERNEL, 87 - )?; 84 + _: { 85 + let bar = bar.access(pdev.as_ref())?; 88 86 89 - let bar = drvdata.bar.access(pdev.as_ref())?; 90 - dev_info!( 91 - pdev.as_ref(), 92 - "pci-testdev data-match count: {}\n", 93 - Self::testdev(info, bar)? 94 - ); 95 - 96 - Ok(drvdata) 87 + dev_info!( 88 + pdev.as_ref(), 89 + "pci-testdev data-match count: {}\n", 90 + Self::testdev(info, bar)? 91 + ); 92 + }, 93 + pdev: pdev.into(), 94 + })) 95 + }) 97 96 } 98 97 99 98 fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {
+2 -4
samples/rust/rust_driver_platform.rs
··· 103 103 fn probe( 104 104 pdev: &platform::Device<Core>, 105 105 info: Option<&Self::IdInfo>, 106 - ) -> Result<Pin<KBox<Self>>> { 106 + ) -> impl PinInit<Self, Error> { 107 107 let dev = pdev.as_ref(); 108 108 109 109 dev_dbg!(dev, "Probe Rust Platform driver sample.\n"); ··· 116 116 Self::properties_parse(dev)?; 117 117 } 118 118 119 - let drvdata = KBox::new(Self { pdev: pdev.into() }, GFP_KERNEL)?; 120 - 121 - Ok(drvdata.into()) 119 + Ok(Self { pdev: pdev.into() }) 122 120 } 123 121 } 124 122
+2 -3
samples/rust/rust_driver_usb.rs
··· 24 24 intf: &usb::Interface<Core>, 25 25 _id: &usb::DeviceId, 26 26 _info: &Self::IdInfo, 27 - ) -> Result<Pin<KBox<Self>>> { 27 + ) -> impl PinInit<Self, Error> { 28 28 let dev: &device::Device<Core> = intf.as_ref(); 29 29 dev_info!(dev, "Rust USB driver sample probed\n"); 30 30 31 - let drvdata = KBox::new(Self { _intf: intf.into() }, GFP_KERNEL)?; 32 - Ok(drvdata.into()) 31 + Ok(Self { _intf: intf.into() }) 33 32 } 34 33 35 34 fn disconnect(intf: &usb::Interface<Core>, _data: Pin<&Self>) {
+147
samples/rust/rust_i2c_client.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Rust I2C client registration sample. 4 + //! 5 + //! An I2C client in Rust cannot exist on its own. To register a new I2C client, 6 + //! it must be bound to a parent device. In this sample driver, a platform device 7 + //! is used as the parent. 8 + //! 9 + 10 + //! ACPI match table test 11 + //! 12 + //! This demonstrates how to test an ACPI-based Rust I2C client registration driver 13 + //! using QEMU with a custom SSDT. 14 + //! 15 + //! Steps: 16 + //! 17 + //! 1. **Create an SSDT source file** (`ssdt.dsl`) with the following content: 18 + //! 19 + //! ```asl 20 + //! DefinitionBlock ("", "SSDT", 2, "TEST", "VIRTACPI", 0x00000001) 21 + //! { 22 + //! Scope (\_SB) 23 + //! { 24 + //! Device (T432) 25 + //! { 26 + //! Name (_HID, "LNUXBEEF") // ACPI hardware ID to match 27 + //! Name (_UID, 1) 28 + //! Name (_STA, 0x0F) // Device present, enabled 29 + //! Name (_CRS, ResourceTemplate () 30 + //! { 31 + //! Memory32Fixed (ReadWrite, 0xFED00000, 0x1000) 32 + //! }) 33 + //! } 34 + //! } 35 + //! } 36 + //! ``` 37 + //! 38 + //! 2. **Compile the table**: 39 + //! 40 + //! ```sh 41 + //! iasl -tc ssdt.dsl 42 + //! ``` 43 + //! 44 + //! This generates `ssdt.aml` 45 + //! 46 + //! 3. **Run QEMU** with the compiled AML file: 47 + //! 48 + //! ```sh 49 + //! qemu-system-x86_64 -m 512M \ 50 + //! -enable-kvm \ 51 + //! -kernel path/to/bzImage \ 52 + //! -append "root=/dev/sda console=ttyS0" \ 53 + //! -hda rootfs.img \ 54 + //! -serial stdio \ 55 + //! -acpitable file=ssdt.aml 56 + //! ``` 57 + //! 58 + //! Requirements: 59 + //! - The `rust_driver_platform` must be present either: 60 + //! - built directly into the kernel (`bzImage`), or 61 + //! - available as a `.ko` file and loadable from `rootfs.img` 62 + //! 63 + //! 4. **Verify it worked** by checking `dmesg`: 64 + //! 65 + //! ``` 66 + //! rust_driver_platform LNUXBEEF:00: Probed with info: '0'. 67 + //! ``` 68 + //! 69 + 70 + use kernel::{ 71 + acpi, 72 + c_str, 73 + device, 74 + devres::Devres, 75 + i2c, 76 + of, 77 + platform, 78 + prelude::*, 79 + sync::aref::ARef, // 80 + }; 81 + 82 + #[pin_data] 83 + struct SampleDriver { 84 + parent_dev: ARef<platform::Device>, 85 + #[pin] 86 + _reg: Devres<i2c::Registration>, 87 + } 88 + 89 + kernel::of_device_table!( 90 + OF_TABLE, 91 + MODULE_OF_TABLE, 92 + <SampleDriver as platform::Driver>::IdInfo, 93 + [(of::DeviceId::new(c_str!("test,rust-device")), ())] 94 + ); 95 + 96 + kernel::acpi_device_table!( 97 + ACPI_TABLE, 98 + MODULE_ACPI_TABLE, 99 + <SampleDriver as platform::Driver>::IdInfo, 100 + [(acpi::DeviceId::new(c_str!("LNUXBEEF")), ())] 101 + ); 102 + 103 + const SAMPLE_I2C_CLIENT_ADDR: u16 = 0x30; 104 + const SAMPLE_I2C_ADAPTER_INDEX: i32 = 0; 105 + const BOARD_INFO: i2c::I2cBoardInfo = 106 + i2c::I2cBoardInfo::new(c_str!("rust_driver_i2c"), SAMPLE_I2C_CLIENT_ADDR); 107 + 108 + impl platform::Driver for SampleDriver { 109 + type IdInfo = (); 110 + const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); 111 + const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); 112 + 113 + fn probe( 114 + pdev: &platform::Device<device::Core>, 115 + _info: Option<&Self::IdInfo>, 116 + ) -> impl PinInit<Self, Error> { 117 + dev_info!( 118 + pdev.as_ref(), 119 + "Probe Rust I2C Client registration sample.\n" 120 + ); 121 + 122 + kernel::try_pin_init!( Self { 123 + parent_dev: pdev.into(), 124 + 125 + _reg <- { 126 + let adapter = i2c::I2cAdapter::get(SAMPLE_I2C_ADAPTER_INDEX)?; 127 + 128 + i2c::Registration::new(&adapter, &BOARD_INFO, pdev.as_ref()) 129 + } 130 + }) 131 + } 132 + 133 + fn unbind(pdev: &platform::Device<device::Core>, _this: Pin<&Self>) { 134 + dev_info!( 135 + pdev.as_ref(), 136 + "Unbind Rust I2C Client registration sample.\n" 137 + ); 138 + } 139 + } 140 + 141 + kernel::module_platform_driver! { 142 + type: SampleDriver, 143 + name: "rust_device_i2c", 144 + authors: ["Danilo Krummrich", "Igor Korotin"], 145 + description: "Rust I2C client registration", 146 + license: "GPL v2", 147 + }