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

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

Pull driver core updates from Danilo Krummrich:
"debugfs:
- Remove unneeded debugfs_file_{get,put}() instances
- Remove last remnants of debugfs_real_fops()
- Allow storing non-const void * in struct debugfs_inode_info::aux

sysfs:
- Switch back to attribute_group::bin_attrs (treewide)
- Switch back to bin_attribute::read()/write() (treewide)
- Constify internal references to 'struct bin_attribute'

Support cache-ids for device-tree systems:
- Add arch hook arch_compact_of_hwid()
- Use arch_compact_of_hwid() to compact MPIDR values on arm64

Rust:
- Device:
- Introduce CoreInternal device context (for bus internal methods)
- Provide generic drvdata accessors for bus devices
- Provide Driver::unbind() callbacks
- Use the infrastructure above for auxiliary, PCI and platform
- Implement Device::as_bound()
- Rename Device::as_ref() to Device::from_raw() (treewide)
- Implement fwnode and device property abstractions
- Implement example usage in the Rust platform sample driver
- Devres:
- Remove the inner reference count (Arc) and use pin-init instead
- Replace Devres::new_foreign_owned() with devres::register()
- Require T to be Send in Devres<T>
- Initialize the data kept inside a Devres last
- Provide an accessor for the Devres associated Device
- Device ID:
- Add support for ACPI device IDs and driver match tables
- Split up generic device ID infrastructure
- Use generic device ID infrastructure in net::phy
- DMA:
- Implement the dma::Device trait
- Add DMA mask accessors to dma::Device
- Implement dma::Device for PCI and platform devices
- Use DMA masks from the DMA sample module
- I/O:
- Implement abstraction for resource regions (struct resource)
- Implement resource-based ioremap() abstractions
- Provide platform device accessors for I/O (remap) requests
- Misc:
- Support fallible PinInit types in Revocable
- Implement Wrapper<T> for Opaque<T>
- Merge pin-init blanket dependencies (for Devres)

Misc:
- Fix OF node leak in auxiliary_device_create()
- Use util macros in device property iterators
- Improve kobject sample code
- Add device_link_test() for testing device link flags
- Fix typo in Documentation/ABI/testing/sysfs-kernel-address_bits
- Hint to prefer container_of_const() over container_of()"

* tag 'driver-core-6.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: (84 commits)
rust: io: fix broken intra-doc links to `platform::Device`
rust: io: fix broken intra-doc link to missing `flags` module
rust: io: mem: enable IoRequest doc-tests
rust: platform: add resource accessors
rust: io: mem: add a generic iomem abstraction
rust: io: add resource abstraction
rust: samples: dma: set DMA mask
rust: platform: implement the `dma::Device` trait
rust: pci: implement the `dma::Device` trait
rust: dma: add DMA addressing capabilities
rust: dma: implement `dma::Device` trait
rust: net::phy Change module_phy_driver macro to use module_device_table macro
rust: net::phy represent DeviceId as transparent wrapper over mdio_device_id
rust: device_id: split out index support into a separate trait
device: rust: rename Device::as_ref() to Device::from_raw()
arm64: cacheinfo: Provide helper to compress MPIDR value into u32
cacheinfo: Add arch hook to compress CPU h/w id into 32 bits for cache-id
cacheinfo: Set cache 'id' based on DT data
container_of: Document container_of() is not to be used in new code
driver core: auxiliary bus: fix OF node leak
...

+2956 -953
+1 -1
Documentation/ABI/testing/sysfs-kernel-address_bits
··· 1 - What: /sys/kernel/address_bit 1 + What: /sys/kernel/address_bits 2 2 Date: May 2023 3 3 KernelVersion: 6.3 4 4 Contact: Thomas Weißschuh <linux@weissschuh.net>
+3
MAINTAINERS
··· 302 302 F: include/linux/fwnode.h 303 303 F: include/linux/fw_table.h 304 304 F: lib/fw_table.c 305 + F: rust/kernel/acpi.rs 305 306 F: tools/power/acpi/ 306 307 307 308 ACPI APEI ··· 7439 7438 F: include/linux/sysfs.h 7440 7439 F: lib/kobj* 7441 7440 F: rust/kernel/device.rs 7441 + F: rust/kernel/device/ 7442 7442 F: rust/kernel/device_id.rs 7443 7443 F: rust/kernel/devres.rs 7444 7444 F: rust/kernel/driver.rs ··· 18717 18715 F: Documentation/ABI/testing/sysfs-firmware-ofw 18718 18716 F: drivers/of/ 18719 18717 F: include/linux/of*.h 18718 + F: rust/helpers/of.c 18720 18719 F: rust/kernel/of.rs 18721 18720 F: scripts/dtc/ 18722 18721 F: tools/testing/selftests/dt/
+17
arch/arm64/include/asm/cache.h
··· 87 87 88 88 #define dma_get_cache_alignment cache_line_size 89 89 90 + /* Compress a u64 MPIDR value into 32 bits. */ 91 + static inline u64 arch_compact_of_hwid(u64 id) 92 + { 93 + u64 aff3 = MPIDR_AFFINITY_LEVEL(id, 3); 94 + 95 + /* 96 + * These bits are expected to be RES0. If not, return a value with 97 + * the upper 32 bits set to force the caller to give up on 32 bit 98 + * cache ids. 99 + */ 100 + if (FIELD_GET(GENMASK_ULL(63, 40), id)) 101 + return id; 102 + 103 + return (aff3 << 24) | FIELD_GET(GENMASK_ULL(23, 0), id); 104 + } 105 + #define arch_compact_of_hwid arch_compact_of_hwid 106 + 90 107 /* 91 108 * Read the effective value of CTR_EL0. 92 109 *
+1 -1
arch/powerpc/kernel/secvar-sysfs.c
··· 121 121 122 122 static const struct attribute_group secvar_attr_group = { 123 123 .attrs = secvar_attrs, 124 - .bin_attrs_new = secvar_bin_attrs, 124 + .bin_attrs = secvar_bin_attrs, 125 125 }; 126 126 __ATTRIBUTE_GROUPS(secvar_attr); 127 127
+1 -1
arch/powerpc/perf/hv-24x7.c
··· 1141 1141 1142 1142 static const struct attribute_group if_group = { 1143 1143 .name = "interface", 1144 - .bin_attrs_new = if_bin_attrs, 1144 + .bin_attrs = if_bin_attrs, 1145 1145 .attrs = if_attrs, 1146 1146 }; 1147 1147
+2 -2
arch/powerpc/platforms/powernv/opal-core.c
··· 208 208 209 209 static struct bin_attribute opal_core_attr __ro_after_init = { 210 210 .attr = {.name = "core", .mode = 0400}, 211 - .read_new = read_opalcore 211 + .read = read_opalcore 212 212 }; 213 213 214 214 /* ··· 607 607 608 608 static const struct attribute_group mpipl_group = { 609 609 .attrs = mpipl_attr, 610 - .bin_attrs_new = mpipl_bin_attr, 610 + .bin_attrs = mpipl_bin_attr, 611 611 }; 612 612 613 613 static int __init opalcore_init(void)
+1 -1
arch/powerpc/platforms/powernv/opal-dump.c
··· 342 342 dump->dump_attr.attr.name = "dump"; 343 343 dump->dump_attr.attr.mode = 0400; 344 344 dump->dump_attr.size = size; 345 - dump->dump_attr.read_new = dump_attr_read; 345 + dump->dump_attr.read = dump_attr_read; 346 346 347 347 dump->id = id; 348 348 dump->size = size;
+1 -1
arch/powerpc/platforms/powernv/opal-elog.c
··· 203 203 elog->raw_attr.attr.name = "raw"; 204 204 elog->raw_attr.attr.mode = 0400; 205 205 elog->raw_attr.size = size; 206 - elog->raw_attr.read_new = raw_attr_read; 206 + elog->raw_attr.read = raw_attr_read; 207 207 208 208 elog->id = id; 209 209 elog->size = size;
+1 -1
arch/powerpc/platforms/powernv/opal-flash.c
··· 493 493 static const struct bin_attribute image_data_attr = { 494 494 .attr = {.name = "image", .mode = 0200}, 495 495 .size = MAX_IMAGE_SIZE, /* Limit image size */ 496 - .write_new = image_data_write, 496 + .write = image_data_write, 497 497 }; 498 498 499 499 static struct kobj_attribute validate_attribute =
+1 -1
arch/powerpc/platforms/powernv/opal-msglog.c
··· 102 102 103 103 static struct bin_attribute opal_msglog_attr __ro_after_init = { 104 104 .attr = {.name = "msglog", .mode = 0400}, 105 - .read_new = opal_msglog_read 105 + .read = opal_msglog_read 106 106 }; 107 107 108 108 struct memcons *__init memcons_init(struct device_node *node, const char *mc_prop_name)
+1 -1
arch/powerpc/platforms/powernv/opal.c
··· 815 815 sysfs_bin_attr_init(attr); 816 816 attr->attr.name = name; 817 817 attr->attr.mode = 0400; 818 - attr->read_new = sysfs_bin_attr_simple_read; 818 + attr->read = sysfs_bin_attr_simple_read; 819 819 attr->private = __va(vals[0]); 820 820 attr->size = vals[1]; 821 821
+1 -1
arch/powerpc/platforms/powernv/ultravisor.c
··· 40 40 41 41 static struct bin_attribute uv_msglog_attr __ro_after_init = { 42 42 .attr = {.name = "msglog", .mode = 0400}, 43 - .read_new = uv_msglog_read 43 + .read = uv_msglog_read 44 44 }; 45 45 46 46 static int __init uv_init(void)
+1 -1
arch/s390/kernel/cpacf.c
··· 101 101 102 102 static const struct attribute_group cpacf_attr_grp = { 103 103 .name = "cpacf", 104 - .bin_attrs_new = cpacf_attrs, 104 + .bin_attrs = cpacf_attrs, 105 105 }; 106 106 107 107 static int __init cpacf_init(void)
+9 -9
arch/s390/kernel/ipl.c
··· 596 596 597 597 static const struct attribute_group ipl_fcp_attr_group = { 598 598 .attrs = ipl_fcp_attrs, 599 - .bin_attrs_new = ipl_fcp_bin_attrs, 599 + .bin_attrs = ipl_fcp_bin_attrs, 600 600 }; 601 601 602 602 static struct attribute *ipl_nvme_attrs[] = { ··· 610 610 611 611 static const struct attribute_group ipl_nvme_attr_group = { 612 612 .attrs = ipl_nvme_attrs, 613 - .bin_attrs_new = ipl_nvme_bin_attrs, 613 + .bin_attrs = ipl_nvme_bin_attrs, 614 614 }; 615 615 616 616 static struct attribute *ipl_eckd_attrs[] = { ··· 623 623 624 624 static const struct attribute_group ipl_eckd_attr_group = { 625 625 .attrs = ipl_eckd_attrs, 626 - .bin_attrs_new = ipl_eckd_bin_attrs, 626 + .bin_attrs = ipl_eckd_bin_attrs, 627 627 }; 628 628 629 629 /* CCW ipl device attributes */ ··· 920 920 921 921 static const struct attribute_group reipl_fcp_attr_group = { 922 922 .attrs = reipl_fcp_attrs, 923 - .bin_attrs_new = reipl_fcp_bin_attrs, 923 + .bin_attrs = reipl_fcp_bin_attrs, 924 924 }; 925 925 926 926 static struct kobj_attribute sys_reipl_fcp_clear_attr = ··· 958 958 959 959 static const struct attribute_group reipl_nvme_attr_group = { 960 960 .attrs = reipl_nvme_attrs, 961 - .bin_attrs_new = reipl_nvme_bin_attrs 961 + .bin_attrs = reipl_nvme_bin_attrs 962 962 }; 963 963 964 964 static ssize_t reipl_nvme_clear_show(struct kobject *kobj, ··· 1051 1051 1052 1052 static const struct attribute_group reipl_eckd_attr_group = { 1053 1053 .attrs = reipl_eckd_attrs, 1054 - .bin_attrs_new = reipl_eckd_bin_attrs 1054 + .bin_attrs = reipl_eckd_bin_attrs 1055 1055 }; 1056 1056 1057 1057 static ssize_t reipl_eckd_clear_show(struct kobject *kobj, ··· 1596 1596 static const struct attribute_group dump_fcp_attr_group = { 1597 1597 .name = IPL_FCP_STR, 1598 1598 .attrs = dump_fcp_attrs, 1599 - .bin_attrs_new = dump_fcp_bin_attrs, 1599 + .bin_attrs = dump_fcp_bin_attrs, 1600 1600 }; 1601 1601 1602 1602 /* NVME dump device attributes */ ··· 1630 1630 static const struct attribute_group dump_nvme_attr_group = { 1631 1631 .name = IPL_NVME_STR, 1632 1632 .attrs = dump_nvme_attrs, 1633 - .bin_attrs_new = dump_nvme_bin_attrs, 1633 + .bin_attrs = dump_nvme_bin_attrs, 1634 1634 }; 1635 1635 1636 1636 /* ECKD dump device attributes */ ··· 1664 1664 static const struct attribute_group dump_eckd_attr_group = { 1665 1665 .name = IPL_ECKD_STR, 1666 1666 .attrs = dump_eckd_attrs, 1667 - .bin_attrs_new = dump_eckd_bin_attrs, 1667 + .bin_attrs = dump_eckd_bin_attrs, 1668 1668 }; 1669 1669 1670 1670 /* CCW dump device attributes */
+1 -1
arch/s390/pci/pci_sysfs.c
··· 218 218 219 219 const struct attribute_group zpci_attr_group = { 220 220 .attrs = zpci_dev_attrs, 221 - .bin_attrs_new = zpci_bin_attrs, 221 + .bin_attrs = zpci_bin_attrs, 222 222 }; 223 223 224 224 static struct attribute *pfip_attrs[] = {
+4 -4
arch/x86/kernel/ksysfs.c
··· 40 40 .name = "data", 41 41 .mode = S_IRUGO, 42 42 }, 43 - .read_new = boot_params_data_read, 43 + .read = boot_params_data_read, 44 44 .size = sizeof(boot_params), 45 45 }; 46 46 ··· 56 56 57 57 static const struct attribute_group boot_params_attr_group = { 58 58 .attrs = boot_params_version_attrs, 59 - .bin_attrs_new = boot_params_data_attrs, 59 + .bin_attrs = boot_params_data_attrs, 60 60 }; 61 61 62 62 static int kobj_to_setup_data_nr(struct kobject *kobj, int *nr) ··· 250 250 .name = "data", 251 251 .mode = S_IRUGO, 252 252 }, 253 - .read_new = setup_data_data_read, 253 + .read = setup_data_data_read, 254 254 }; 255 255 256 256 static struct attribute *setup_data_type_attrs[] = { ··· 265 265 266 266 static const struct attribute_group setup_data_attr_group = { 267 267 .attrs = setup_data_type_attrs, 268 - .bin_attrs_new = setup_data_data_attrs, 268 + .bin_attrs = setup_data_data_attrs, 269 269 }; 270 270 271 271 static int __init create_setup_data_node(struct kobject *parent,
+5 -7
block/blk-mq-debugfs.c
··· 521 521 static int blk_mq_debugfs_show(struct seq_file *m, void *v) 522 522 { 523 523 const struct blk_mq_debugfs_attr *attr = m->private; 524 - void *data = d_inode(m->file->f_path.dentry->d_parent)->i_private; 524 + void *data = debugfs_get_aux(m->file); 525 525 526 526 return attr->show(data, m); 527 527 } ··· 531 531 { 532 532 struct seq_file *m = file->private_data; 533 533 const struct blk_mq_debugfs_attr *attr = m->private; 534 - void *data = d_inode(file->f_path.dentry->d_parent)->i_private; 534 + void *data = debugfs_get_aux(file); 535 535 536 536 /* 537 537 * Attributes that only implement .seq_ops are read-only and 'attr' is ··· 546 546 static int blk_mq_debugfs_open(struct inode *inode, struct file *file) 547 547 { 548 548 const struct blk_mq_debugfs_attr *attr = inode->i_private; 549 - void *data = d_inode(file->f_path.dentry->d_parent)->i_private; 549 + void *data = debugfs_get_aux(file); 550 550 struct seq_file *m; 551 551 int ret; 552 552 ··· 612 612 if (IS_ERR_OR_NULL(parent)) 613 613 return; 614 614 615 - d_inode(parent)->i_private = data; 616 - 617 615 for (; attr->name; attr++) 618 - debugfs_create_file(attr->name, attr->mode, parent, 619 - (void *)attr, &blk_mq_debugfs_fops); 616 + debugfs_create_file_aux(attr->name, attr->mode, parent, 617 + (void *)attr, data, &blk_mq_debugfs_fops); 620 618 } 621 619 622 620 void blk_mq_debugfs_register(struct request_queue *q)
+2 -2
drivers/accel/habanalabs/common/sysfs.c
··· 446 446 static const struct bin_attribute bin_attr_eeprom = { 447 447 .attr = {.name = "eeprom", .mode = (0444)}, 448 448 .size = PAGE_SIZE, 449 - .read_new = eeprom_read_handler 449 + .read = eeprom_read_handler 450 450 }; 451 451 452 452 static struct attribute *hl_dev_attrs[] = { ··· 479 479 480 480 static struct attribute_group hl_dev_attr_group = { 481 481 .attrs = hl_dev_attrs, 482 - .bin_attrs_new = hl_dev_bin_attrs, 482 + .bin_attrs = hl_dev_bin_attrs, 483 483 }; 484 484 485 485 static struct attribute_group hl_dev_clks_attr_group;
+1 -1
drivers/acpi/bgrt.c
··· 47 47 48 48 static const struct attribute_group bgrt_attribute_group = { 49 49 .attrs = bgrt_attributes, 50 - .bin_attrs_new = bgrt_bin_attributes, 50 + .bin_attrs = bgrt_bin_attributes, 51 51 }; 52 52 53 53 int __init acpi_parse_bgrt(struct acpi_table_header *table)
+2 -2
drivers/acpi/sysfs.c
··· 372 372 } 373 373 374 374 table_attr->attr.size = table_header->length; 375 - table_attr->attr.read_new = acpi_table_show; 375 + table_attr->attr.read = acpi_table_show; 376 376 table_attr->attr.attr.name = table_attr->filename; 377 377 table_attr->attr.attr.mode = 0400; 378 378 ··· 495 495 if (!data_attr) 496 496 return -ENOMEM; 497 497 sysfs_attr_init(&data_attr->attr.attr); 498 - data_attr->attr.read_new = acpi_data_show; 498 + data_attr->attr.read = acpi_data_show; 499 499 data_attr->attr.attr.mode = 0400; 500 500 return acpi_data_objs[i].fn(th, data_attr); 501 501 }
+2
drivers/base/auxiliary.c
··· 399 399 { 400 400 struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 401 401 402 + of_node_put(dev->of_node); 402 403 kfree(auxdev); 403 404 } 404 405 ··· 436 435 437 436 ret = auxiliary_device_init(auxdev); 438 437 if (ret) { 438 + of_node_put(auxdev->dev.of_node); 439 439 kfree(auxdev); 440 440 return NULL; 441 441 }
+50
drivers/base/cacheinfo.c
··· 8 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 9 10 10 #include <linux/acpi.h> 11 + #include <linux/bitfield.h> 11 12 #include <linux/bitops.h> 12 13 #include <linux/cacheinfo.h> 13 14 #include <linux/compiler.h> ··· 184 183 return of_property_read_bool(np, "cache-unified"); 185 184 } 186 185 186 + static bool match_cache_node(struct device_node *cpu, 187 + const struct device_node *cache_node) 188 + { 189 + struct device_node *prev, *cache = of_find_next_cache_node(cpu); 190 + 191 + while (cache) { 192 + if (cache == cache_node) { 193 + of_node_put(cache); 194 + return true; 195 + } 196 + 197 + prev = cache; 198 + cache = of_find_next_cache_node(cache); 199 + of_node_put(prev); 200 + } 201 + 202 + return false; 203 + } 204 + 205 + #ifndef arch_compact_of_hwid 206 + #define arch_compact_of_hwid(_x) (_x) 207 + #endif 208 + 209 + static void cache_of_set_id(struct cacheinfo *this_leaf, 210 + struct device_node *cache_node) 211 + { 212 + struct device_node *cpu; 213 + u32 min_id = ~0; 214 + 215 + for_each_of_cpu_node(cpu) { 216 + u64 id = of_get_cpu_hwid(cpu, 0); 217 + 218 + id = arch_compact_of_hwid(id); 219 + if (FIELD_GET(GENMASK_ULL(63, 32), id)) { 220 + of_node_put(cpu); 221 + return; 222 + } 223 + 224 + if (match_cache_node(cpu, cache_node)) 225 + min_id = min(min_id, id); 226 + } 227 + 228 + if (min_id != ~0) { 229 + this_leaf->id = min_id; 230 + this_leaf->attributes |= CACHE_ID; 231 + } 232 + } 233 + 187 234 static void cache_of_set_props(struct cacheinfo *this_leaf, 188 235 struct device_node *np) 189 236 { ··· 247 198 cache_get_line_size(this_leaf, np); 248 199 cache_nr_sets(this_leaf, np); 249 200 cache_associativity(this_leaf); 201 + cache_of_set_id(this_leaf, np); 250 202 } 251 203 252 204 static int cache_setup_of_node(unsigned int cpu)
+36 -37
drivers/base/core.c
··· 460 460 struct device_link *link = to_devlink(dev); 461 461 const char *output; 462 462 463 - if (link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) 463 + if (device_link_test(link, DL_FLAG_AUTOREMOVE_SUPPLIER)) 464 464 output = "supplier unbind"; 465 - else if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) 465 + else if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER)) 466 466 output = "consumer unbind"; 467 467 else 468 468 output = "never"; ··· 476 476 { 477 477 struct device_link *link = to_devlink(dev); 478 478 479 - return sysfs_emit(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME)); 479 + return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_PM_RUNTIME)); 480 480 } 481 481 static DEVICE_ATTR_RO(runtime_pm); 482 482 ··· 485 485 { 486 486 struct device_link *link = to_devlink(dev); 487 487 488 - return sysfs_emit(buf, "%d\n", 489 - !!(link->flags & DL_FLAG_SYNC_STATE_ONLY)); 488 + return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)); 490 489 } 491 490 static DEVICE_ATTR_RO(sync_state_only); 492 491 ··· 791 792 if (link->consumer != consumer) 792 793 continue; 793 794 794 - if (link->flags & DL_FLAG_INFERRED && 795 + if (device_link_test(link, DL_FLAG_INFERRED) && 795 796 !(flags & DL_FLAG_INFERRED)) 796 797 link->flags &= ~DL_FLAG_INFERRED; 797 798 798 799 if (flags & DL_FLAG_PM_RUNTIME) { 799 - if (!(link->flags & DL_FLAG_PM_RUNTIME)) { 800 + if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) { 800 801 pm_runtime_new_link(consumer); 801 802 link->flags |= DL_FLAG_PM_RUNTIME; 802 803 } ··· 806 807 807 808 if (flags & DL_FLAG_STATELESS) { 808 809 kref_get(&link->kref); 809 - if (link->flags & DL_FLAG_SYNC_STATE_ONLY && 810 - !(link->flags & DL_FLAG_STATELESS)) { 810 + if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY) && 811 + !device_link_test(link, DL_FLAG_STATELESS)) { 811 812 link->flags |= DL_FLAG_STATELESS; 812 813 goto reorder; 813 814 } else { ··· 822 823 * update the existing link to stay around longer. 823 824 */ 824 825 if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) { 825 - if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) { 826 + if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER)) { 826 827 link->flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER; 827 828 link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER; 828 829 } ··· 830 831 link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER | 831 832 DL_FLAG_AUTOREMOVE_SUPPLIER); 832 833 } 833 - if (!(link->flags & DL_FLAG_MANAGED)) { 834 + if (!device_link_test(link, DL_FLAG_MANAGED)) { 834 835 kref_get(&link->kref); 835 836 link->flags |= DL_FLAG_MANAGED; 836 837 device_link_init_status(link, consumer, supplier); 837 838 } 838 - if (link->flags & DL_FLAG_SYNC_STATE_ONLY && 839 + if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY) && 839 840 !(flags & DL_FLAG_SYNC_STATE_ONLY)) { 840 841 link->flags &= ~DL_FLAG_SYNC_STATE_ONLY; 841 842 goto reorder; ··· 939 940 940 941 static void device_link_put_kref(struct device_link *link) 941 942 { 942 - if (link->flags & DL_FLAG_STATELESS) 943 + if (device_link_test(link, DL_FLAG_STATELESS)) 943 944 kref_put(&link->kref, __device_link_del); 944 945 else if (!device_is_registered(link->consumer)) 945 946 __device_link_del(&link->kref); ··· 1003 1004 if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) { 1004 1005 WRITE_ONCE(link->status, DL_STATE_AVAILABLE); 1005 1006 } else { 1006 - WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY)); 1007 + WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)); 1007 1008 WRITE_ONCE(link->status, DL_STATE_DORMANT); 1008 1009 } 1009 1010 } ··· 1071 1072 device_links_write_lock(); 1072 1073 1073 1074 list_for_each_entry(link, &dev->links.suppliers, c_node) { 1074 - if (!(link->flags & DL_FLAG_MANAGED)) 1075 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1075 1076 continue; 1076 1077 1077 1078 if (link->status != DL_STATE_AVAILABLE && 1078 - !(link->flags & DL_FLAG_SYNC_STATE_ONLY)) { 1079 + !device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)) { 1079 1080 1080 1081 if (dev_is_best_effort(dev) && 1081 - link->flags & DL_FLAG_INFERRED && 1082 + device_link_test(link, DL_FLAG_INFERRED) && 1082 1083 !link->supplier->can_match) { 1083 1084 ret = -EAGAIN; 1084 1085 continue; ··· 1127 1128 return; 1128 1129 1129 1130 list_for_each_entry(link, &dev->links.consumers, s_node) { 1130 - if (!(link->flags & DL_FLAG_MANAGED)) 1131 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1131 1132 continue; 1132 1133 if (link->status != DL_STATE_ACTIVE) 1133 1134 return; ··· 1267 1268 device_links_write_lock(); 1268 1269 1269 1270 list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) { 1270 - if (!(link->flags & DL_FLAG_MANAGED)) 1271 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1271 1272 continue; 1272 1273 1273 1274 if (link->status != DL_STATE_AVAILABLE) { ··· 1328 1329 device_links_write_lock(); 1329 1330 1330 1331 list_for_each_entry(link, &dev->links.consumers, s_node) { 1331 - if (!(link->flags & DL_FLAG_MANAGED)) 1332 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1332 1333 continue; 1333 1334 1334 1335 /* ··· 1344 1345 WARN_ON(link->status != DL_STATE_DORMANT); 1345 1346 WRITE_ONCE(link->status, DL_STATE_AVAILABLE); 1346 1347 1347 - if (link->flags & DL_FLAG_AUTOPROBE_CONSUMER) 1348 + if (device_link_test(link, DL_FLAG_AUTOPROBE_CONSUMER)) 1348 1349 driver_deferred_probe_add(link->consumer); 1349 1350 } 1350 1351 ··· 1356 1357 list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) { 1357 1358 struct device *supplier; 1358 1359 1359 - if (!(link->flags & DL_FLAG_MANAGED)) 1360 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1360 1361 continue; 1361 1362 1362 1363 supplier = link->supplier; 1363 - if (link->flags & DL_FLAG_SYNC_STATE_ONLY) { 1364 + if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)) { 1364 1365 /* 1365 1366 * When DL_FLAG_SYNC_STATE_ONLY is set, it means no 1366 1367 * other DL_MANAGED_LINK_FLAGS have been set. So, it's ··· 1368 1369 */ 1369 1370 device_link_drop_managed(link); 1370 1371 } else if (dev_is_best_effort(dev) && 1371 - link->flags & DL_FLAG_INFERRED && 1372 + device_link_test(link, DL_FLAG_INFERRED) && 1372 1373 link->status != DL_STATE_CONSUMER_PROBE && 1373 1374 !link->supplier->can_match) { 1374 1375 /* ··· 1420 1421 struct device_link *link, *ln; 1421 1422 1422 1423 list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) { 1423 - if (!(link->flags & DL_FLAG_MANAGED)) 1424 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1424 1425 continue; 1425 1426 1426 - if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) { 1427 + if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER)) { 1427 1428 device_link_drop_managed(link); 1428 1429 continue; 1429 1430 } ··· 1435 1436 if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) { 1436 1437 WRITE_ONCE(link->status, DL_STATE_AVAILABLE); 1437 1438 } else { 1438 - WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY)); 1439 + WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)); 1439 1440 WRITE_ONCE(link->status, DL_STATE_DORMANT); 1440 1441 } 1441 1442 } ··· 1460 1461 device_links_write_lock(); 1461 1462 1462 1463 list_for_each_entry(link, &dev->links.consumers, s_node) { 1463 - if (!(link->flags & DL_FLAG_MANAGED)) 1464 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1464 1465 continue; 1465 1466 1466 1467 /* ··· 1497 1498 device_links_write_lock(); 1498 1499 1499 1500 list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) { 1500 - if (!(link->flags & DL_FLAG_MANAGED)) 1501 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1501 1502 continue; 1502 1503 1503 - WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER); 1504 + WARN_ON(device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER)); 1504 1505 WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND); 1505 1506 1506 1507 /* ··· 1509 1510 * has moved to DL_STATE_SUPPLIER_UNBIND. 1510 1511 */ 1511 1512 if (link->status == DL_STATE_SUPPLIER_UNBIND && 1512 - link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER) 1513 + device_link_test(link, DL_FLAG_AUTOREMOVE_SUPPLIER)) 1513 1514 device_link_drop_managed(link); 1514 1515 1515 1516 WRITE_ONCE(link->status, DL_STATE_DORMANT); ··· 1543 1544 device_links_write_lock(); 1544 1545 1545 1546 list_for_each_entry(link, &dev->links.consumers, s_node) { 1546 - if (!(link->flags & DL_FLAG_MANAGED)) 1547 + if (!device_link_test(link, DL_FLAG_MANAGED)) 1547 1548 continue; 1548 1549 1549 1550 if (link->status == DL_STATE_CONSUMER_PROBE ··· 1585 1586 list_for_each_entry(link, &dev->links.consumers, s_node) { 1586 1587 enum device_link_state status; 1587 1588 1588 - if (!(link->flags & DL_FLAG_MANAGED) || 1589 - link->flags & DL_FLAG_SYNC_STATE_ONLY) 1589 + if (!device_link_test(link, DL_FLAG_MANAGED) || 1590 + device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)) 1590 1591 continue; 1591 1592 1592 1593 status = link->status; ··· 1742 1743 1743 1744 static void fw_devlink_relax_link(struct device_link *link) 1744 1745 { 1745 - if (!(link->flags & DL_FLAG_INFERRED)) 1746 + if (!device_link_test(link, DL_FLAG_INFERRED)) 1746 1747 return; 1747 1748 1748 1749 if (device_link_flag_is_sync_state_only(link->flags)) ··· 1778 1779 struct device_link *link = to_devlink(dev); 1779 1780 struct device *sup = link->supplier; 1780 1781 1781 - if (!(link->flags & DL_FLAG_MANAGED) || 1782 + if (!device_link_test(link, DL_FLAG_MANAGED) || 1782 1783 link->status == DL_STATE_ACTIVE || sup->state_synced || 1783 1784 !dev_has_sync_state(sup)) 1784 1785 return 0; ··· 2060 2061 * such due to a cycle. 2061 2062 */ 2062 2063 if (device_link_flag_is_sync_state_only(dev_link->flags) && 2063 - !(dev_link->flags & DL_FLAG_CYCLE)) 2064 + !device_link_test(dev_link, DL_FLAG_CYCLE)) 2064 2065 continue; 2065 2066 2066 2067 if (__fw_devlink_relax_cycles(con_handle,
+1 -1
drivers/base/devcoredump.c
··· 140 140 }; 141 141 142 142 static const struct attribute_group devcd_dev_group = { 143 - .bin_attrs_new = devcd_dev_bin_attrs, 143 + .bin_attrs = devcd_dev_bin_attrs, 144 144 }; 145 145 146 146 static const struct attribute_group *devcd_dev_groups[] = {
+3 -3
drivers/base/firmware_loader/sysfs.c
··· 359 359 static const struct bin_attribute firmware_attr_data = { 360 360 .attr = { .name = "data", .mode = 0644 }, 361 361 .size = 0, 362 - .read_new = firmware_data_read, 363 - .write_new = firmware_data_write, 362 + .read = firmware_data_read, 363 + .write = firmware_data_write, 364 364 }; 365 365 366 366 static struct attribute *fw_dev_attrs[] = { ··· 381 381 382 382 static const struct attribute_group fw_dev_attr_group = { 383 383 .attrs = fw_dev_attrs, 384 - .bin_attrs_new = fw_dev_bin_attrs, 384 + .bin_attrs = fw_dev_bin_attrs, 385 385 #ifdef CONFIG_FW_UPLOAD 386 386 .is_visible = fw_upload_is_visible, 387 387 #endif
+1 -1
drivers/base/node.c
··· 597 597 598 598 static const struct attribute_group node_dev_group = { 599 599 .attrs = node_dev_attrs, 600 - .bin_attrs_new = node_dev_bin_attrs, 600 + .bin_attrs = node_dev_bin_attrs, 601 601 }; 602 602 603 603 static const struct attribute_group *node_dev_groups[] = {
+1 -1
drivers/base/power/main.c
··· 2052 2052 idx = device_links_read_lock(); 2053 2053 2054 2054 list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { 2055 - if (!(link->flags & DL_FLAG_PM_RUNTIME)) 2055 + if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) 2056 2056 continue; 2057 2057 2058 2058 if (!dev_pm_smart_suspend(link->supplier) &&
+3 -3
drivers/base/power/runtime.c
··· 302 302 device_links_read_lock_held()) { 303 303 int retval; 304 304 305 - if (!(link->flags & DL_FLAG_PM_RUNTIME)) 305 + if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) 306 306 continue; 307 307 308 308 retval = pm_runtime_get_sync(link->supplier); ··· 1905 1905 1906 1906 list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, 1907 1907 device_links_read_lock_held()) 1908 - if (link->flags & DL_FLAG_PM_RUNTIME) { 1908 + if (device_link_test(link, DL_FLAG_PM_RUNTIME)) { 1909 1909 link->supplier_preactivated = true; 1910 1910 pm_runtime_get_sync(link->supplier); 1911 1911 } ··· 1959 1959 */ 1960 1960 void pm_runtime_drop_link(struct device_link *link) 1961 1961 { 1962 - if (!(link->flags & DL_FLAG_PM_RUNTIME)) 1962 + if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) 1963 1963 return; 1964 1964 1965 1965 pm_runtime_drop_link_count(link->consumer);
+1 -1
drivers/base/topology.c
··· 179 179 180 180 static const struct attribute_group topology_attr_group = { 181 181 .attrs = default_attrs, 182 - .bin_attrs_new = bin_attrs, 182 + .bin_attrs = bin_attrs, 183 183 .is_visible = topology_is_visible, 184 184 .name = "topology" 185 185 };
+2 -1
drivers/cpufreq/rcpufreq_dt.rs
··· 20 20 /// Finds exact supply name from the OF node. 21 21 fn find_supply_name_exact(dev: &Device, name: &str) -> Option<CString> { 22 22 let prop_name = CString::try_from_fmt(fmt!("{}-supply", name)).ok()?; 23 - dev.property_present(&prop_name) 23 + dev.fwnode()? 24 + .property_present(&prop_name) 24 25 .then(|| CString::try_from_fmt(fmt!("{name}")).ok()) 25 26 .flatten() 26 27 }
+1 -1
drivers/cxl/port.c
··· 181 181 }; 182 182 183 183 static const struct attribute_group cxl_cdat_attribute_group = { 184 - .bin_attrs_new = cxl_cdat_bin_attributes, 184 + .bin_attrs = cxl_cdat_bin_attributes, 185 185 .is_bin_visible = cxl_port_bin_attr_is_visible, 186 186 }; 187 187
+1 -1
drivers/firmware/efi/mokvar-table.c
··· 340 340 mokvar_sysfs->bin_attr.attr.name = mokvar_entry->name; 341 341 mokvar_sysfs->bin_attr.attr.mode = 0400; 342 342 mokvar_sysfs->bin_attr.size = mokvar_entry->data_size; 343 - mokvar_sysfs->bin_attr.read_new = efi_mokvar_sysfs_read; 343 + mokvar_sysfs->bin_attr.read = efi_mokvar_sysfs_read; 344 344 345 345 err = sysfs_create_bin_file(mokvar_kobj, 346 346 &mokvar_sysfs->bin_attr);
+1 -1
drivers/firmware/google/cbmem.c
··· 86 86 87 87 static const struct attribute_group cbmem_entry_group = { 88 88 .attrs = attrs, 89 - .bin_attrs_new = bin_attrs, 89 + .bin_attrs = bin_attrs, 90 90 }; 91 91 92 92 static const struct attribute_group *dev_groups[] = {
+1 -1
drivers/firmware/google/gsmi.c
··· 530 530 531 531 static const struct bin_attribute eventlog_bin_attr = { 532 532 .attr = {.name = "append_to_eventlog", .mode = 0200}, 533 - .write_new = eventlog_write, 533 + .write = eventlog_write, 534 534 }; 535 535 536 536 static ssize_t gsmi_clear_eventlog_store(struct kobject *kobj,
+1 -1
drivers/firmware/google/memconsole.c
··· 28 28 29 29 static struct bin_attribute memconsole_bin_attr = { 30 30 .attr = {.name = "log", .mode = 0444}, 31 - .read_new = memconsole_read, 31 + .read = memconsole_read, 32 32 }; 33 33 34 34 void memconsole_setup(ssize_t (*read_func)(char *, loff_t, size_t))
+2 -2
drivers/firmware/google/vpd.c
··· 121 121 info->bin_attr.attr.name = info->key; 122 122 info->bin_attr.attr.mode = 0444; 123 123 info->bin_attr.size = value_len; 124 - info->bin_attr.read_new = vpd_attrib_read; 124 + info->bin_attr.read = vpd_attrib_read; 125 125 info->bin_attr.private = info; 126 126 127 127 info->value = value; ··· 201 201 sec->bin_attr.attr.name = sec->raw_name; 202 202 sec->bin_attr.attr.mode = 0444; 203 203 sec->bin_attr.size = size; 204 - sec->bin_attr.read_new = vpd_section_read; 204 + sec->bin_attr.read = vpd_section_read; 205 205 sec->bin_attr.private = sec; 206 206 207 207 err = sysfs_create_bin_file(vpd_kobj, &sec->bin_attr);
+1 -1
drivers/firmware/qemu_fw_cfg.c
··· 476 476 477 477 static const struct bin_attribute fw_cfg_sysfs_attr_raw = { 478 478 .attr = { .name = "raw", .mode = S_IRUSR }, 479 - .read_new = fw_cfg_sysfs_read_raw, 479 + .read = fw_cfg_sysfs_read_raw, 480 480 }; 481 481 482 482 /*
+2 -2
drivers/fsi/fsi-core.c
··· 613 613 .mode = 0600, 614 614 }, 615 615 .size = 0, 616 - .read_new = fsi_slave_sysfs_raw_read, 617 - .write_new = fsi_slave_sysfs_raw_write, 616 + .read = fsi_slave_sysfs_raw_read, 617 + .write = fsi_slave_sysfs_raw_write, 618 618 }; 619 619 620 620 static void fsi_slave_release(struct device *dev)
+3 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
··· 4125 4125 static const struct bin_attribute psp_vbflash_bin_attr = { 4126 4126 .attr = {.name = "psp_vbflash", .mode = 0660}, 4127 4127 .size = 0, 4128 - .write_new = amdgpu_psp_vbflash_write, 4129 - .read_new = amdgpu_psp_vbflash_read, 4128 + .write = amdgpu_psp_vbflash_write, 4129 + .read = amdgpu_psp_vbflash_read, 4130 4130 }; 4131 4131 4132 4132 /** ··· 4189 4189 4190 4190 const struct attribute_group amdgpu_flash_attr_group = { 4191 4191 .attrs = flash_attrs, 4192 - .bin_attrs_new = bin_flash_attrs, 4192 + .bin_attrs = bin_flash_attrs, 4193 4193 .is_bin_visible = amdgpu_bin_flash_attr_is_visible, 4194 4194 .is_visible = amdgpu_flash_attr_is_visible, 4195 4195 };
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
··· 2124 2124 con->badpages_attr = bin_attr_gpu_vram_bad_pages; 2125 2125 sysfs_bin_attr_init(&con->badpages_attr); 2126 2126 bin_attrs[0] = &con->badpages_attr; 2127 - group.bin_attrs_new = bin_attrs; 2127 + group.bin_attrs = bin_attrs; 2128 2128 } 2129 2129 2130 2130 r = sysfs_create_group(&adev->dev->kobj, &group);
+2 -2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
··· 723 723 static const struct bin_attribute data_attr = { 724 724 .attr = {.name = "hdcp_srm", .mode = 0664}, 725 725 .size = PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, /* Limit SRM size */ 726 - .write_new = srm_data_write, 727 - .read_new = srm_data_read, 726 + .write = srm_data_write, 727 + .read = srm_data_read, 728 728 }; 729 729 730 730 struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev,
+2 -2
drivers/gpu/drm/drm_sysfs.c
··· 319 319 .attr.name = "edid", 320 320 .attr.mode = 0444, 321 321 .size = 0, 322 - .read_new = edid_show, 322 + .read = edid_show, 323 323 }; 324 324 325 325 static const struct bin_attribute *const connector_bin_attrs[] = { ··· 329 329 330 330 static const struct attribute_group connector_dev_group = { 331 331 .attrs = connector_dev_attrs, 332 - .bin_attrs_new = connector_bin_attrs, 332 + .bin_attrs = connector_bin_attrs, 333 333 }; 334 334 335 335 static const struct attribute_group *connector_dev_groups[] = {
+2 -2
drivers/gpu/drm/i915/i915_gpu_error.c
··· 2506 2506 .attr.name = "error", 2507 2507 .attr.mode = S_IRUSR | S_IWUSR, 2508 2508 .size = 0, 2509 - .read_new = error_state_read, 2510 - .write_new = error_state_write, 2509 + .read = error_state_read, 2510 + .write = error_state_write, 2511 2511 }; 2512 2512 2513 2513 void i915_gpu_error_sysfs_setup(struct drm_i915_private *i915)
+4 -4
drivers/gpu/drm/i915/i915_sysfs.c
··· 140 140 static const struct bin_attribute dpf_attrs = { 141 141 .attr = {.name = "l3_parity", .mode = (S_IRUSR | S_IWUSR)}, 142 142 .size = GEN7_L3LOG_SIZE, 143 - .read_new = i915_l3_read, 144 - .write_new = i915_l3_write, 143 + .read = i915_l3_read, 144 + .write = i915_l3_write, 145 145 .mmap = NULL, 146 146 .private = (void *)0 147 147 }; ··· 149 149 static const struct bin_attribute dpf_attrs_1 = { 150 150 .attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)}, 151 151 .size = GEN7_L3LOG_SIZE, 152 - .read_new = i915_l3_read, 153 - .write_new = i915_l3_write, 152 + .read = i915_l3_read, 153 + .write = i915_l3_write, 154 154 .mmap = NULL, 155 155 .private = (void *)1 156 156 };
+2 -2
drivers/gpu/drm/lima/lima_drv.c
··· 362 362 .attr.name = "error", 363 363 .attr.mode = 0600, 364 364 .size = 0, 365 - .read_new = lima_error_state_read, 366 - .write_new = lima_error_state_write, 365 + .read = lima_error_state_read, 366 + .write = lima_error_state_write, 367 367 }; 368 368 369 369 static int lima_pdev_probe(struct platform_device *pdev)
+4 -34
drivers/gpu/drm/xlnx/zynqmp_dp.c
··· 1869 1869 static ssize_t zynqmp_dp_pattern_read(struct file *file, char __user *user_buf, 1870 1870 size_t count, loff_t *ppos) 1871 1871 { 1872 - struct dentry *dentry = file->f_path.dentry; 1873 1872 struct zynqmp_dp *dp = file->private_data; 1874 1873 char buf[16]; 1875 1874 ssize_t ret; 1876 - 1877 - ret = debugfs_file_get(dentry); 1878 - if (unlikely(ret)) 1879 - return ret; 1880 1875 1881 1876 scoped_guard(mutex, &dp->lock) 1882 1877 ret = snprintf(buf, sizeof(buf), "%s\n", 1883 1878 test_pattern_str[dp->test.pattern]); 1884 1879 1885 - debugfs_file_put(dentry); 1886 1880 return simple_read_from_buffer(user_buf, count, ppos, buf, ret); 1887 1881 } 1888 1882 ··· 1884 1890 const char __user *user_buf, 1885 1891 size_t count, loff_t *ppos) 1886 1892 { 1887 - struct dentry *dentry = file->f_path.dentry; 1888 1893 struct zynqmp_dp *dp = file->private_data; 1889 1894 char buf[16]; 1890 1895 ssize_t ret; 1891 1896 int pattern; 1892 1897 1893 - ret = debugfs_file_get(dentry); 1894 - if (unlikely(ret)) 1895 - return ret; 1896 - 1897 1898 ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, 1898 1899 count); 1899 1900 if (ret < 0) 1900 - goto out; 1901 + return ret; 1901 1902 buf[ret] = '\0'; 1902 1903 1903 1904 pattern = sysfs_match_string(test_pattern_str, buf); 1904 - if (pattern < 0) { 1905 - ret = -EINVAL; 1906 - goto out; 1907 - } 1905 + if (pattern < 0) 1906 + return -EINVAL; 1908 1907 1909 1908 mutex_lock(&dp->lock); 1910 1909 dp->test.pattern = pattern; ··· 1906 1919 dp->test.custom) ?: ret; 1907 1920 mutex_unlock(&dp->lock); 1908 1921 1909 - out: 1910 - debugfs_file_put(dentry); 1911 1922 return ret; 1912 1923 } 1913 1924 ··· 2011 2026 static ssize_t zynqmp_dp_custom_read(struct file *file, char __user *user_buf, 2012 2027 size_t count, loff_t *ppos) 2013 2028 { 2014 - struct dentry *dentry = file->f_path.dentry; 2015 2029 struct zynqmp_dp *dp = file->private_data; 2016 2030 ssize_t ret; 2017 - 2018 - ret = debugfs_file_get(dentry); 2019 - if (unlikely(ret)) 2020 - return ret; 2021 2031 2022 2032 mutex_lock(&dp->lock); 2023 2033 ret = simple_read_from_buffer(user_buf, count, ppos, &dp->test.custom, 2024 2034 sizeof(dp->test.custom)); 2025 2035 mutex_unlock(&dp->lock); 2026 - 2027 - debugfs_file_put(dentry); 2028 2036 return ret; 2029 2037 } 2030 2038 ··· 2025 2047 const char __user *user_buf, 2026 2048 size_t count, loff_t *ppos) 2027 2049 { 2028 - struct dentry *dentry = file->f_path.dentry; 2029 2050 struct zynqmp_dp *dp = file->private_data; 2030 2051 ssize_t ret; 2031 2052 char buf[sizeof(dp->test.custom)]; 2032 2053 2033 - ret = debugfs_file_get(dentry); 2034 - if (unlikely(ret)) 2035 - return ret; 2036 - 2037 2054 ret = simple_write_to_buffer(buf, sizeof(buf), ppos, user_buf, count); 2038 2055 if (ret < 0) 2039 - goto out; 2056 + return ret; 2040 2057 2041 2058 mutex_lock(&dp->lock); 2042 2059 memcpy(dp->test.custom, buf, ret); ··· 2039 2066 ret = zynqmp_dp_set_test_pattern(dp, dp->test.pattern, 2040 2067 dp->test.custom) ?: ret; 2041 2068 mutex_unlock(&dp->lock); 2042 - 2043 - out: 2044 - debugfs_file_put(dentry); 2045 2069 return ret; 2046 2070 } 2047 2071
+5 -2
drivers/gpu/nova-core/driver.rs
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 - use kernel::{auxiliary, bindings, c_str, device::Core, pci, prelude::*}; 3 + use kernel::{auxiliary, bindings, c_str, device::Core, pci, prelude::*, sync::Arc}; 4 4 5 5 use crate::gpu::Gpu; 6 6 ··· 34 34 pdev.enable_device_mem()?; 35 35 pdev.set_master(); 36 36 37 - let bar = pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0"))?; 37 + let bar = Arc::pin_init( 38 + pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")), 39 + GFP_KERNEL, 40 + )?; 38 41 39 42 let this = KBox::pin_init( 40 43 try_pin_init!(Self {
+3 -3
drivers/gpu/nova-core/gpu.rs
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 - use kernel::{device, devres::Devres, error::code::*, pci, prelude::*}; 3 + use kernel::{device, devres::Devres, error::code::*, pci, prelude::*, sync::Arc}; 4 4 5 5 use crate::driver::Bar0; 6 6 use crate::firmware::{Firmware, FIRMWARE_VERSION}; ··· 161 161 pub(crate) struct Gpu { 162 162 spec: Spec, 163 163 /// MMIO mapping of PCI BAR 0 164 - bar: Devres<Bar0>, 164 + bar: Arc<Devres<Bar0>>, 165 165 fw: Firmware, 166 166 } 167 167 168 168 impl Gpu { 169 169 pub(crate) fn new( 170 170 pdev: &pci::Device<device::Bound>, 171 - devres_bar: Devres<Bar0>, 171 + devres_bar: Arc<Devres<Bar0>>, 172 172 ) -> Result<impl PinInit<Self>> { 173 173 let bar = devres_bar.access(pdev.as_ref())?; 174 174 let spec = Spec::new(bar)?;
+1 -1
drivers/hid/hid-core.c
··· 2824 2824 }; 2825 2825 static const struct attribute_group hid_dev_group = { 2826 2826 .attrs = hid_dev_attrs, 2827 - .bin_attrs_new = hid_dev_bin_attrs, 2827 + .bin_attrs = hid_dev_bin_attrs, 2828 2828 }; 2829 2829 __ATTRIBUTE_GROUPS(hid_dev); 2830 2830
+1 -1
drivers/hid/hid-roccat-arvo.c
··· 258 258 259 259 static const struct attribute_group arvo_group = { 260 260 .attrs = arvo_attrs, 261 - .bin_attrs_new = arvo_bin_attributes, 261 + .bin_attrs = arvo_bin_attributes, 262 262 }; 263 263 264 264 static const struct attribute_group *arvo_groups[] = {
+4 -4
drivers/hid/hid-roccat-common.h
··· 71 71 static const struct bin_attribute bin_attr_ ## thingy = { \ 72 72 .attr = { .name = #thingy, .mode = 0660 }, \ 73 73 .size = SIZE, \ 74 - .read_new = roccat_common2_sysfs_read_ ## thingy, \ 75 - .write_new = roccat_common2_sysfs_write_ ## thingy \ 74 + .read = roccat_common2_sysfs_read_ ## thingy, \ 75 + .write = roccat_common2_sysfs_write_ ## thingy \ 76 76 } 77 77 78 78 #define ROCCAT_COMMON2_BIN_ATTRIBUTE_R(thingy, COMMAND, SIZE) \ ··· 80 80 static const struct bin_attribute bin_attr_ ## thingy = { \ 81 81 .attr = { .name = #thingy, .mode = 0440 }, \ 82 82 .size = SIZE, \ 83 - .read_new = roccat_common2_sysfs_read_ ## thingy, \ 83 + .read = roccat_common2_sysfs_read_ ## thingy, \ 84 84 } 85 85 86 86 #define ROCCAT_COMMON2_BIN_ATTRIBUTE_W(thingy, COMMAND, SIZE) \ ··· 88 88 static const struct bin_attribute bin_attr_ ## thingy = { \ 89 89 .attr = { .name = #thingy, .mode = 0220 }, \ 90 90 .size = SIZE, \ 91 - .write_new = roccat_common2_sysfs_write_ ## thingy \ 91 + .write = roccat_common2_sysfs_write_ ## thingy \ 92 92 } 93 93 94 94 #endif
+5 -5
drivers/hid/hid-roccat-isku.c
··· 181 181 static const struct bin_attribute bin_attr_##thingy = { \ 182 182 .attr = { .name = #thingy, .mode = 0660 }, \ 183 183 .size = ISKU_SIZE_ ## THINGY, \ 184 - .read_new = isku_sysfs_read_ ## thingy, \ 185 - .write_new = isku_sysfs_write_ ## thingy \ 184 + .read = isku_sysfs_read_ ## thingy, \ 185 + .write = isku_sysfs_write_ ## thingy \ 186 186 } 187 187 188 188 #define ISKU_BIN_ATTR_R(thingy, THINGY) \ ··· 190 190 static const struct bin_attribute bin_attr_##thingy = { \ 191 191 .attr = { .name = #thingy, .mode = 0440 }, \ 192 192 .size = ISKU_SIZE_ ## THINGY, \ 193 - .read_new = isku_sysfs_read_ ## thingy, \ 193 + .read = isku_sysfs_read_ ## thingy, \ 194 194 } 195 195 196 196 #define ISKU_BIN_ATTR_W(thingy, THINGY) \ ··· 198 198 static const struct bin_attribute bin_attr_##thingy = { \ 199 199 .attr = { .name = #thingy, .mode = 0220 }, \ 200 200 .size = ISKU_SIZE_ ## THINGY, \ 201 - .write_new = isku_sysfs_write_ ## thingy \ 201 + .write = isku_sysfs_write_ ## thingy \ 202 202 } 203 203 204 204 ISKU_BIN_ATTR_RW(macro, MACRO); ··· 238 238 239 239 static const struct attribute_group isku_group = { 240 240 .attrs = isku_attrs, 241 - .bin_attrs_new = isku_bin_attributes, 241 + .bin_attrs = isku_bin_attributes, 242 242 }; 243 243 244 244 static const struct attribute_group *isku_groups[] = {
+3 -3
drivers/hid/hid-roccat-kone.c
··· 385 385 static const struct bin_attribute bin_attr_profile##number = { \ 386 386 .attr = { .name = "profile" #number, .mode = 0660 }, \ 387 387 .size = sizeof(struct kone_profile), \ 388 - .read_new = kone_sysfs_read_profilex, \ 389 - .write_new = kone_sysfs_write_profilex, \ 388 + .read = kone_sysfs_read_profilex, \ 389 + .write = kone_sysfs_write_profilex, \ 390 390 .private = &profile_numbers[number-1], \ 391 391 } 392 392 PROFILE_ATTR(1); ··· 646 646 647 647 static const struct attribute_group kone_group = { 648 648 .attrs = kone_attrs, 649 - .bin_attrs_new = kone_bin_attributes, 649 + .bin_attrs = kone_bin_attributes, 650 650 }; 651 651 652 652 static const struct attribute_group *kone_groups[] = {
+7 -7
drivers/hid/hid-roccat-koneplus.c
··· 153 153 static const struct bin_attribute bin_attr_##thingy = { \ 154 154 .attr = { .name = #thingy, .mode = 0660 }, \ 155 155 .size = KONEPLUS_SIZE_ ## THINGY, \ 156 - .read_new = koneplus_sysfs_read_ ## thingy, \ 157 - .write_new = koneplus_sysfs_write_ ## thingy \ 156 + .read = koneplus_sysfs_read_ ## thingy, \ 157 + .write = koneplus_sysfs_write_ ## thingy \ 158 158 } 159 159 160 160 #define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \ ··· 162 162 static const struct bin_attribute bin_attr_##thingy = { \ 163 163 .attr = { .name = #thingy, .mode = 0440 }, \ 164 164 .size = KONEPLUS_SIZE_ ## THINGY, \ 165 - .read_new = koneplus_sysfs_read_ ## thingy, \ 165 + .read = koneplus_sysfs_read_ ## thingy, \ 166 166 } 167 167 168 168 #define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \ ··· 170 170 static const struct bin_attribute bin_attr_##thingy = { \ 171 171 .attr = { .name = #thingy, .mode = 0220 }, \ 172 172 .size = KONEPLUS_SIZE_ ## THINGY, \ 173 - .write_new = koneplus_sysfs_write_ ## thingy \ 173 + .write = koneplus_sysfs_write_ ## thingy \ 174 174 } 175 175 KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL); 176 176 KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK); ··· 222 222 static const struct bin_attribute bin_attr_profile##number##_settings = { \ 223 223 .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ 224 224 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, \ 225 - .read_new = koneplus_sysfs_read_profilex_settings, \ 225 + .read = koneplus_sysfs_read_profilex_settings, \ 226 226 .private = &profile_numbers[number-1], \ 227 227 }; \ 228 228 static const struct bin_attribute bin_attr_profile##number##_buttons = { \ 229 229 .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ 230 230 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, \ 231 - .read_new = koneplus_sysfs_read_profilex_buttons, \ 231 + .read = koneplus_sysfs_read_profilex_buttons, \ 232 232 .private = &profile_numbers[number-1], \ 233 233 }; 234 234 PROFILE_ATTR(1); ··· 346 346 347 347 static const struct attribute_group koneplus_group = { 348 348 .attrs = koneplus_attrs, 349 - .bin_attrs_new = koneplus_bin_attributes, 349 + .bin_attrs = koneplus_bin_attributes, 350 350 }; 351 351 352 352 static const struct attribute_group *koneplus_groups[] = {
+1 -1
drivers/hid/hid-roccat-konepure.c
··· 62 62 }; 63 63 64 64 static const struct attribute_group konepure_group = { 65 - .bin_attrs_new = konepure_bin_attrs, 65 + .bin_attrs = konepure_bin_attrs, 66 66 }; 67 67 68 68 static const struct attribute_group *konepure_groups[] = {
+6 -6
drivers/hid/hid-roccat-kovaplus.c
··· 196 196 static const struct bin_attribute bin_attr_##thingy = { \ 197 197 .attr = { .name = #thingy, .mode = 0660 }, \ 198 198 .size = KOVAPLUS_SIZE_ ## THINGY, \ 199 - .read_new = kovaplus_sysfs_read_ ## thingy, \ 200 - .write_new = kovaplus_sysfs_write_ ## thingy \ 199 + .read = kovaplus_sysfs_read_ ## thingy, \ 200 + .write = kovaplus_sysfs_write_ ## thingy \ 201 201 } 202 202 203 203 #define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \ ··· 205 205 static const struct bin_attribute bin_attr_##thingy = { \ 206 206 .attr = { .name = #thingy, .mode = 0220 }, \ 207 207 .size = KOVAPLUS_SIZE_ ## THINGY, \ 208 - .write_new = kovaplus_sysfs_write_ ## thingy \ 208 + .write = kovaplus_sysfs_write_ ## thingy \ 209 209 } 210 210 KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL); 211 211 KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO); ··· 252 252 static const struct bin_attribute bin_attr_profile##number##_settings = { \ 253 253 .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ 254 254 .size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \ 255 - .read_new = kovaplus_sysfs_read_profilex_settings, \ 255 + .read = kovaplus_sysfs_read_profilex_settings, \ 256 256 .private = &profile_numbers[number-1], \ 257 257 }; \ 258 258 static const struct bin_attribute bin_attr_profile##number##_buttons = { \ 259 259 .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ 260 260 .size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \ 261 - .read_new = kovaplus_sysfs_read_profilex_buttons, \ 261 + .read = kovaplus_sysfs_read_profilex_buttons, \ 262 262 .private = &profile_numbers[number-1], \ 263 263 }; 264 264 PROFILE_ATTR(1); ··· 399 399 400 400 static const struct attribute_group kovaplus_group = { 401 401 .attrs = kovaplus_attrs, 402 - .bin_attrs_new = kovaplus_bin_attributes, 402 + .bin_attrs = kovaplus_bin_attributes, 403 403 }; 404 404 405 405 static const struct attribute_group *kovaplus_groups[] = {
+2 -2
drivers/hid/hid-roccat-lua.c
··· 88 88 static const struct bin_attribute lua_ ## thingy ## _attr = { \ 89 89 .attr = { .name = #thingy, .mode = 0660 }, \ 90 90 .size = LUA_SIZE_ ## THINGY, \ 91 - .read_new = lua_sysfs_read_ ## thingy, \ 92 - .write_new = lua_sysfs_write_ ## thingy \ 91 + .read = lua_sysfs_read_ ## thingy, \ 92 + .write = lua_sysfs_write_ ## thingy \ 93 93 }; 94 94 95 95 LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
+7 -7
drivers/hid/hid-roccat-pyra.c
··· 154 154 static const struct bin_attribute bin_attr_##thingy = { \ 155 155 .attr = { .name = #thingy, .mode = 0660 }, \ 156 156 .size = PYRA_SIZE_ ## THINGY, \ 157 - .read_new = pyra_sysfs_read_ ## thingy, \ 158 - .write_new = pyra_sysfs_write_ ## thingy \ 157 + .read = pyra_sysfs_read_ ## thingy, \ 158 + .write = pyra_sysfs_write_ ## thingy \ 159 159 } 160 160 161 161 #define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \ ··· 163 163 static const struct bin_attribute bin_attr_##thingy = { \ 164 164 .attr = { .name = #thingy, .mode = 0440 }, \ 165 165 .size_new = PYRA_SIZE_ ## THINGY, \ 166 - .read_new = pyra_sysfs_read_ ## thingy, \ 166 + .read = pyra_sysfs_read_ ## thingy, \ 167 167 } 168 168 169 169 #define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \ ··· 171 171 static const struct bin_attribute bin_attr_##thingy = { \ 172 172 .attr = { .name = #thingy, .mode = 0220 }, \ 173 173 .size = PYRA_SIZE_ ## THINGY, \ 174 - .write_new = pyra_sysfs_write_ ## thingy \ 174 + .write = pyra_sysfs_write_ ## thingy \ 175 175 } 176 176 177 177 PYRA_BIN_ATTRIBUTE_W(control, CONTROL); ··· 219 219 static const struct bin_attribute bin_attr_profile##number##_settings = { \ 220 220 .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ 221 221 .size = PYRA_SIZE_PROFILE_SETTINGS, \ 222 - .read_new = pyra_sysfs_read_profilex_settings, \ 222 + .read = pyra_sysfs_read_profilex_settings, \ 223 223 .private = &profile_numbers[number-1], \ 224 224 }; \ 225 225 static const struct bin_attribute bin_attr_profile##number##_buttons = { \ 226 226 .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ 227 227 .size = PYRA_SIZE_PROFILE_BUTTONS, \ 228 - .read_new = pyra_sysfs_read_profilex_buttons, \ 228 + .read = pyra_sysfs_read_profilex_buttons, \ 229 229 .private = &profile_numbers[number-1], \ 230 230 }; 231 231 PROFILE_ATTR(1); ··· 355 355 356 356 static const struct attribute_group pyra_group = { 357 357 .attrs = pyra_attrs, 358 - .bin_attrs_new = pyra_bin_attributes, 358 + .bin_attrs = pyra_bin_attributes, 359 359 }; 360 360 361 361 static const struct attribute_group *pyra_groups[] = {
+1 -1
drivers/hid/hid-roccat-ryos.c
··· 70 70 }; 71 71 72 72 static const struct attribute_group ryos_group = { 73 - .bin_attrs_new = ryos_bin_attrs, 73 + .bin_attrs = ryos_bin_attrs, 74 74 }; 75 75 76 76 static const struct attribute_group *ryos_groups[] = {
+1 -1
drivers/hid/hid-roccat-savu.c
··· 42 42 }; 43 43 44 44 static const struct attribute_group savu_group = { 45 - .bin_attrs_new = savu_bin_attrs, 45 + .bin_attrs = savu_bin_attrs, 46 46 }; 47 47 48 48 static const struct attribute_group *savu_groups[] = {
+2 -2
drivers/i2c/i2c-slave-eeprom.c
··· 165 165 sysfs_bin_attr_init(&eeprom->bin); 166 166 eeprom->bin.attr.name = "slave-eeprom"; 167 167 eeprom->bin.attr.mode = S_IRUSR | S_IWUSR; 168 - eeprom->bin.read_new = i2c_slave_eeprom_bin_read; 169 - eeprom->bin.write_new = i2c_slave_eeprom_bin_write; 168 + eeprom->bin.read = i2c_slave_eeprom_bin_read; 169 + eeprom->bin.write = i2c_slave_eeprom_bin_write; 170 170 eeprom->bin.size = size; 171 171 172 172 ret = sysfs_create_bin_file(&client->dev.kobj, &eeprom->bin);
+1 -1
drivers/iio/imu/bno055/bno055.c
··· 1365 1365 1366 1366 static const struct attribute_group bno055_attrs_group = { 1367 1367 .attrs = bno055_attrs, 1368 - .bin_attrs_new = bno055_bin_attrs, 1368 + .bin_attrs = bno055_bin_attrs, 1369 1369 }; 1370 1370 1371 1371 static const struct iio_info bno055_info = {
-28
drivers/infiniband/hw/hfi1/debugfs.c
··· 22 22 23 23 static struct dentry *hfi1_dbg_root; 24 24 25 - /* wrappers to enforce srcu in seq file */ 26 - ssize_t hfi1_seq_read(struct file *file, char __user *buf, size_t size, 27 - loff_t *ppos) 28 - { 29 - struct dentry *d = file->f_path.dentry; 30 - ssize_t r; 31 - 32 - r = debugfs_file_get(d); 33 - if (unlikely(r)) 34 - return r; 35 - r = seq_read(file, buf, size, ppos); 36 - debugfs_file_put(d); 37 - return r; 38 - } 39 - 40 - loff_t hfi1_seq_lseek(struct file *file, loff_t offset, int whence) 41 - { 42 - struct dentry *d = file->f_path.dentry; 43 - loff_t r; 44 - 45 - r = debugfs_file_get(d); 46 - if (unlikely(r)) 47 - return r; 48 - r = seq_lseek(file, offset, whence); 49 - debugfs_file_put(d); 50 - return r; 51 - } 52 - 53 25 #define private2dd(file) (file_inode(file)->i_private) 54 26 #define private2ppd(file) (file_inode(file)->i_private) 55 27
+2 -7
drivers/infiniband/hw/hfi1/debugfs.h
··· 33 33 static const struct file_operations _##name##_file_ops = { \ 34 34 .owner = THIS_MODULE, \ 35 35 .open = _##name##_open, \ 36 - .read = hfi1_seq_read, \ 37 - .llseek = hfi1_seq_lseek, \ 36 + .read = seq_read, \ 37 + .llseek = seq_lseek, \ 38 38 .release = seq_release \ 39 39 } 40 - 41 - 42 - ssize_t hfi1_seq_read(struct file *file, char __user *buf, size_t size, 43 - loff_t *ppos); 44 - loff_t hfi1_seq_lseek(struct file *file, loff_t offset, int whence); 45 40 46 41 #ifdef CONFIG_DEBUG_FS 47 42 void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd);
-9
drivers/infiniband/hw/hfi1/fault.c
··· 104 104 goto free_data; 105 105 } 106 106 107 - ret = debugfs_file_get(file->f_path.dentry); 108 - if (unlikely(ret)) 109 - goto free_data; 110 107 ptr = data; 111 108 token = ptr; 112 109 for (ptr = data; *ptr; ptr = end + 1, token = ptr) { ··· 151 154 } 152 155 ret = len; 153 156 154 - debugfs_file_put(file->f_path.dentry); 155 157 free_data: 156 158 kfree(data); 157 159 return ret; ··· 169 173 data = kcalloc(datalen, sizeof(*data), GFP_KERNEL); 170 174 if (!data) 171 175 return -ENOMEM; 172 - ret = debugfs_file_get(file->f_path.dentry); 173 - if (unlikely(ret)) 174 - goto free_data; 175 176 bit = find_first_bit(fault->opcodes, bitsize); 176 177 while (bit < bitsize) { 177 178 zero = find_next_zero_bit(fault->opcodes, bitsize, bit); ··· 182 189 bit); 183 190 bit = find_next_bit(fault->opcodes, bitsize, zero); 184 191 } 185 - debugfs_file_put(file->f_path.dentry); 186 192 data[size - 1] = '\n'; 187 193 data[size] = '\0'; 188 194 ret = simple_read_from_buffer(buf, len, pos, data, size); 189 - free_data: 190 195 kfree(data); 191 196 return ret; 192 197 }
+1 -1
drivers/infiniband/hw/hfi1/sysfs.c
··· 134 134 static const struct attribute_group port_cc_group = { 135 135 .name = "CCMgtA", 136 136 .attrs = port_cc_attributes, 137 - .bin_attrs_new = port_cc_bin_attributes, 137 + .bin_attrs = port_cc_bin_attributes, 138 138 }; 139 139 140 140 /* Start sc2vl */
+1 -1
drivers/infiniband/hw/qib/qib_sysfs.c
··· 295 295 static const struct attribute_group port_ccmgta_attribute_group = { 296 296 .name = "CCMgtA", 297 297 .is_bin_visible = qib_ccmgta_is_bin_visible, 298 - .bin_attrs_new = port_ccmgta_attributes, 298 + .bin_attrs = port_ccmgta_attributes, 299 299 }; 300 300 301 301 /* Start sl2vl */
+1 -1
drivers/input/touchscreen/goodix_berlin_core.c
··· 707 707 }; 708 708 709 709 static const struct attribute_group goodix_berlin_attr_group = { 710 - .bin_attrs_new = goodix_berlin_bin_attrs, 710 + .bin_attrs = goodix_berlin_bin_attrs, 711 711 }; 712 712 713 713 const struct attribute_group *goodix_berlin_groups[] = {
+1 -1
drivers/leds/led-class.c
··· 91 91 NULL, 92 92 }; 93 93 static const struct attribute_group led_trigger_group = { 94 - .bin_attrs_new = led_trigger_bin_attrs, 94 + .bin_attrs = led_trigger_bin_attrs, 95 95 }; 96 96 #endif 97 97
+1 -1
drivers/media/pci/solo6x10/solo6x10-core.c
··· 432 432 sysfs_attr_init(&sdram_attr->attr); 433 433 sdram_attr->attr.name = "sdram"; 434 434 sdram_attr->attr.mode = 0440; 435 - sdram_attr->read_new = sdram_show; 435 + sdram_attr->read = sdram_show; 436 436 sdram_attr->size = solo_dev->sdram_size; 437 437 438 438 if (device_create_bin_file(dev, sdram_attr)) {
+1 -1
drivers/misc/c2port/core.c
··· 888 888 889 889 static const struct attribute_group c2port_group = { 890 890 .attrs = c2port_attrs, 891 - .bin_attrs_new = c2port_bin_attrs, 891 + .bin_attrs = c2port_bin_attrs, 892 892 .bin_size = c2port_bin_attr_size, 893 893 }; 894 894
+2 -2
drivers/misc/ds1682.c
··· 194 194 .mode = S_IRUGO | S_IWUSR, 195 195 }, 196 196 .size = DS1682_EEPROM_SIZE, 197 - .read_new = ds1682_eeprom_read, 198 - .write_new = ds1682_eeprom_write, 197 + .read = ds1682_eeprom_read, 198 + .write = ds1682_eeprom_write, 199 199 }; 200 200 201 201 static int ds1682_nvmem_read(void *priv, unsigned int offset, void *val,
+1 -1
drivers/misc/eeprom/max6875.c
··· 127 127 .mode = S_IRUGO, 128 128 }, 129 129 .size = USER_EEPROM_SIZE, 130 - .read_new = max6875_read, 130 + .read = max6875_read, 131 131 }; 132 132 133 133 static int max6875_probe(struct i2c_client *client)
+1 -1
drivers/misc/ocxl/sysfs.c
··· 155 155 info->attr_global_mmio.attr.name = "global_mmio_area"; 156 156 info->attr_global_mmio.attr.mode = 0600; 157 157 info->attr_global_mmio.size = info->afu->config.global_mmio_size; 158 - info->attr_global_mmio.read_new = global_mmio_read; 158 + info->attr_global_mmio.read = global_mmio_read; 159 159 info->attr_global_mmio.mmap = global_mmio_mmap; 160 160 rc = device_create_bin_file(&info->dev, &info->attr_global_mmio); 161 161 if (rc) {
+2 -2
drivers/misc/pch_phub.c
··· 655 655 .mode = S_IRUGO | S_IWUSR, 656 656 }, 657 657 .size = PCH_PHUB_OROM_SIZE + 1, 658 - .read_new = pch_phub_bin_read, 659 - .write_new = pch_phub_bin_write, 658 + .read = pch_phub_bin_read, 659 + .write = pch_phub_bin_write, 660 660 }; 661 661 662 662 static int pch_phub_probe(struct pci_dev *pdev,
+2 -2
drivers/misc/sram.c
··· 85 85 return -ENOMEM; 86 86 87 87 part->battr.attr.mode = S_IRUSR | S_IWUSR; 88 - part->battr.read_new = sram_read; 89 - part->battr.write_new = sram_write; 88 + part->battr.read = sram_read; 89 + part->battr.write = sram_write; 90 90 part->battr.size = block->size; 91 91 92 92 return device_create_bin_file(sram->dev, &part->battr);
+1 -1
drivers/mtd/spi-nor/sysfs.c
··· 104 104 .is_visible = spi_nor_sysfs_is_visible, 105 105 .is_bin_visible = spi_nor_sysfs_is_bin_visible, 106 106 .attrs = spi_nor_sysfs_entries, 107 - .bin_attrs_new = spi_nor_sysfs_bin_entries, 107 + .bin_attrs = spi_nor_sysfs_bin_entries, 108 108 }; 109 109 110 110 const struct attribute_group *spi_nor_sysfs_groups[] = {
+10 -5
drivers/net/ethernet/netronome/nfp/nfp_net_debugfs.c
··· 77 77 static int nfp_tx_q_show(struct seq_file *file, void *data); 78 78 DEFINE_SHOW_ATTRIBUTE(nfp_tx_q); 79 79 80 - static int nfp_tx_q_show(struct seq_file *file, void *data) 80 + static int __nfp_tx_q_show(struct seq_file *file, void *data, bool is_xdp) 81 81 { 82 82 struct nfp_net_r_vector *r_vec = file->private; 83 83 struct nfp_net_tx_ring *tx_ring; ··· 86 86 87 87 rtnl_lock(); 88 88 89 - if (debugfs_real_fops(file->file) == &nfp_tx_q_fops) 90 - tx_ring = r_vec->tx_ring; 91 - else 89 + if (is_xdp) 92 90 tx_ring = r_vec->xdp_ring; 91 + else 92 + tx_ring = r_vec->tx_ring; 93 93 if (!r_vec->nfp_net || !tx_ring) 94 94 goto out; 95 95 nn = r_vec->nfp_net; ··· 115 115 return 0; 116 116 } 117 117 118 + static int nfp_tx_q_show(struct seq_file *file, void *data) 119 + { 120 + return __nfp_tx_q_show(file, data, false); 121 + } 122 + 118 123 static int nfp_xdp_q_show(struct seq_file *file, void *data) 119 124 { 120 - return nfp_tx_q_show(file, data); 125 + return __nfp_tx_q_show(file, data, true); 121 126 } 122 127 DEFINE_SHOW_ATTRIBUTE(nfp_xdp_q); 123 128
+5 -5
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
··· 2946 2946 static const struct bin_attribute bin_attr_crb = { 2947 2947 .attr = { .name = "crb", .mode = 0644 }, 2948 2948 .size = 0, 2949 - .read_new = netxen_sysfs_read_crb, 2950 - .write_new = netxen_sysfs_write_crb, 2949 + .read = netxen_sysfs_read_crb, 2950 + .write = netxen_sysfs_write_crb, 2951 2951 }; 2952 2952 2953 2953 static const struct bin_attribute bin_attr_mem = { 2954 2954 .attr = { .name = "mem", .mode = 0644 }, 2955 2955 .size = 0, 2956 - .read_new = netxen_sysfs_read_mem, 2957 - .write_new = netxen_sysfs_write_mem, 2956 + .read = netxen_sysfs_read_mem, 2957 + .write = netxen_sysfs_write_mem, 2958 2958 }; 2959 2959 2960 2960 static ssize_t ··· 3082 3082 static const struct bin_attribute bin_attr_dimm = { 3083 3083 .attr = { .name = "dimm", .mode = 0644 }, 3084 3084 .size = sizeof(struct netxen_dimm_cfg), 3085 - .read_new = netxen_sysfs_read_dimm, 3085 + .read = netxen_sysfs_read_dimm, 3086 3086 }; 3087 3087 3088 3088
+17 -17
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
··· 1195 1195 static const struct bin_attribute bin_attr_crb = { 1196 1196 .attr = { .name = "crb", .mode = 0644 }, 1197 1197 .size = 0, 1198 - .read_new = qlcnic_sysfs_read_crb, 1199 - .write_new = qlcnic_sysfs_write_crb, 1198 + .read = qlcnic_sysfs_read_crb, 1199 + .write = qlcnic_sysfs_write_crb, 1200 1200 }; 1201 1201 1202 1202 static const struct bin_attribute bin_attr_mem = { 1203 1203 .attr = { .name = "mem", .mode = 0644 }, 1204 1204 .size = 0, 1205 - .read_new = qlcnic_sysfs_read_mem, 1206 - .write_new = qlcnic_sysfs_write_mem, 1205 + .read = qlcnic_sysfs_read_mem, 1206 + .write = qlcnic_sysfs_write_mem, 1207 1207 }; 1208 1208 1209 1209 static const struct bin_attribute bin_attr_npar_config = { 1210 1210 .attr = { .name = "npar_config", .mode = 0644 }, 1211 1211 .size = 0, 1212 - .read_new = qlcnic_sysfs_read_npar_config, 1213 - .write_new = qlcnic_sysfs_write_npar_config, 1212 + .read = qlcnic_sysfs_read_npar_config, 1213 + .write = qlcnic_sysfs_write_npar_config, 1214 1214 }; 1215 1215 1216 1216 static const struct bin_attribute bin_attr_pci_config = { 1217 1217 .attr = { .name = "pci_config", .mode = 0644 }, 1218 1218 .size = 0, 1219 - .read_new = qlcnic_sysfs_read_pci_config, 1219 + .read = qlcnic_sysfs_read_pci_config, 1220 1220 }; 1221 1221 1222 1222 static const struct bin_attribute bin_attr_port_stats = { 1223 1223 .attr = { .name = "port_stats", .mode = 0644 }, 1224 1224 .size = 0, 1225 - .read_new = qlcnic_sysfs_get_port_stats, 1226 - .write_new = qlcnic_sysfs_clear_port_stats, 1225 + .read = qlcnic_sysfs_get_port_stats, 1226 + .write = qlcnic_sysfs_clear_port_stats, 1227 1227 }; 1228 1228 1229 1229 static const struct bin_attribute bin_attr_esw_stats = { 1230 1230 .attr = { .name = "esw_stats", .mode = 0644 }, 1231 1231 .size = 0, 1232 - .read_new = qlcnic_sysfs_get_esw_stats, 1233 - .write_new = qlcnic_sysfs_clear_esw_stats, 1232 + .read = qlcnic_sysfs_get_esw_stats, 1233 + .write = qlcnic_sysfs_clear_esw_stats, 1234 1234 }; 1235 1235 1236 1236 static const struct bin_attribute bin_attr_esw_config = { 1237 1237 .attr = { .name = "esw_config", .mode = 0644 }, 1238 1238 .size = 0, 1239 - .read_new = qlcnic_sysfs_read_esw_config, 1240 - .write_new = qlcnic_sysfs_write_esw_config, 1239 + .read = qlcnic_sysfs_read_esw_config, 1240 + .write = qlcnic_sysfs_write_esw_config, 1241 1241 }; 1242 1242 1243 1243 static const struct bin_attribute bin_attr_pm_config = { 1244 1244 .attr = { .name = "pm_config", .mode = 0644 }, 1245 1245 .size = 0, 1246 - .read_new = qlcnic_sysfs_read_pm_config, 1247 - .write_new = qlcnic_sysfs_write_pm_config, 1246 + .read = qlcnic_sysfs_read_pm_config, 1247 + .write = qlcnic_sysfs_write_pm_config, 1248 1248 }; 1249 1249 1250 1250 static const struct bin_attribute bin_attr_flash = { 1251 1251 .attr = { .name = "flash", .mode = 0644 }, 1252 1252 .size = 0, 1253 - .read_new = qlcnic_83xx_sysfs_flash_read_handler, 1254 - .write_new = qlcnic_83xx_sysfs_flash_write_handler, 1253 + .read = qlcnic_83xx_sysfs_flash_read_handler, 1254 + .write = qlcnic_83xx_sysfs_flash_write_handler, 1255 1255 }; 1256 1256 1257 1257 #ifdef CONFIG_QLCNIC_HWMON
+2 -2
drivers/net/phy/spi_ks8995.c
··· 401 401 .mode = 0600, 402 402 }, 403 403 .size = KS8995_REGS_SIZE, 404 - .read_new = ks8995_registers_read, 405 - .write_new = ks8995_registers_write, 404 + .read = ks8995_registers_read, 405 + .write = ks8995_registers_write, 406 406 }; 407 407 408 408 /* ------------------------------------------------------------------------ */
+1 -1
drivers/net/wireless/ti/wlcore/sysfs.c
··· 121 121 122 122 static const struct bin_attribute fwlog_attr = { 123 123 .attr = { .name = "fwlog", .mode = 0400 }, 124 - .read_new = wl1271_sysfs_read_fwlog, 124 + .read = wl1271_sysfs_read_fwlog, 125 125 }; 126 126 127 127 int wlcore_sysfs_init(struct wl1271 *wl)
+7 -7
drivers/nvmem/core.c
··· 376 376 .name = "nvmem", 377 377 .mode = 0644, 378 378 }, 379 - .read_new = bin_attr_nvmem_read, 380 - .write_new = bin_attr_nvmem_write, 379 + .read = bin_attr_nvmem_read, 380 + .write = bin_attr_nvmem_write, 381 381 }; 382 382 383 383 static const struct bin_attribute *const nvmem_bin_attributes[] = { ··· 386 386 }; 387 387 388 388 static const struct attribute_group nvmem_bin_group = { 389 - .bin_attrs_new = nvmem_bin_attributes, 389 + .bin_attrs = nvmem_bin_attributes, 390 390 .attrs = nvmem_attrs, 391 391 .is_bin_visible = nvmem_bin_attr_is_visible, 392 392 .bin_size = nvmem_bin_attr_size, ··· 402 402 .attr = { 403 403 .name = "eeprom", 404 404 }, 405 - .read_new = bin_attr_nvmem_read, 406 - .write_new = bin_attr_nvmem_write, 405 + .read = bin_attr_nvmem_read, 406 + .write = bin_attr_nvmem_write, 407 407 }; 408 408 409 409 /* ··· 492 492 entry->bit_offset); 493 493 attrs[i].attr.mode = 0444 & nvmem_bin_attr_get_umode(nvmem); 494 494 attrs[i].size = entry->bytes; 495 - attrs[i].read_new = &nvmem_cell_attr_read; 495 + attrs[i].read = &nvmem_cell_attr_read; 496 496 attrs[i].private = entry; 497 497 if (!attrs[i].attr.name) { 498 498 ret = -ENOMEM; ··· 503 503 i++; 504 504 } 505 505 506 - group.bin_attrs_new = pattrs; 506 + group.bin_attrs = pattrs; 507 507 508 508 ret = device_add_group(&nvmem->dev, &group); 509 509 if (ret)
+1 -1
drivers/of/kobj.c
··· 77 77 pp->attr.attr.name = safe_name(&np->kobj, pp->name); 78 78 pp->attr.attr.mode = secure ? 0400 : 0444; 79 79 pp->attr.size = secure ? 0 : pp->length; 80 - pp->attr.read_new = of_node_property_read; 80 + pp->attr.read = of_node_property_read; 81 81 82 82 rc = sysfs_create_bin_file(&np->kobj, &pp->attr); 83 83 WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np);
+10
drivers/of/unittest-data/tests-platform.dtsi
··· 37 37 test-device@2 { 38 38 compatible = "test,rust-device"; 39 39 reg = <0x2>; 40 + 41 + test,u32-prop = <0xdeadbeef>; 42 + test,i16-array = /bits/ 16 <1 2 (-3) (-4)>; 43 + 44 + ref_child_0: child-0 { 45 + test,ref-arg = <&ref_child_1 0x20 0x32>; 46 + }; 47 + ref_child_1: child-1 { 48 + test,ref-arg = <&ref_child_0 0x10 0x64>; 49 + }; 40 50 }; 41 51 }; 42 52
+2
drivers/of/unittest.c
··· 1856 1856 of_platform_populate(np, match, NULL, &test_bus->dev); 1857 1857 for_each_child_of_node(np, child) { 1858 1858 for_each_child_of_node(child, grandchild) { 1859 + if (!of_property_present(grandchild, "compatible")) 1860 + continue; 1859 1861 pdev = of_find_device_by_node(grandchild); 1860 1862 unittest(pdev, 1861 1863 "Could not create device for node '%pOFn'\n",
+1 -1
drivers/pci/hotplug/acpiphp_ibm.c
··· 98 98 .name = "apci_table", 99 99 .mode = S_IRUGO, 100 100 }, 101 - .read_new = ibm_read_apci_table, 101 + .read = ibm_read_apci_table, 102 102 .write = NULL, 103 103 }; 104 104 static struct acpiphp_attention_info ibm_attention_info =
+1 -1
drivers/pci/p2pdma.c
··· 196 196 197 197 static const struct attribute_group p2pmem_group = { 198 198 .attrs = p2pmem_attrs, 199 - .bin_attrs_new = p2pmem_bin_attrs, 199 + .bin_attrs = p2pmem_bin_attrs, 200 200 .name = "p2pmem", 201 201 }; 202 202
+6 -6
drivers/pci/pci-sysfs.c
··· 857 857 } 858 858 859 859 static const struct attribute_group pci_dev_config_attr_group = { 860 - .bin_attrs_new = pci_dev_config_attrs, 860 + .bin_attrs = pci_dev_config_attrs, 861 861 .bin_size = pci_dev_config_attr_bin_size, 862 862 }; 863 863 ··· 1004 1004 b->legacy_io->attr.name = "legacy_io"; 1005 1005 b->legacy_io->size = 0xffff; 1006 1006 b->legacy_io->attr.mode = 0600; 1007 - b->legacy_io->read_new = pci_read_legacy_io; 1008 - b->legacy_io->write_new = pci_write_legacy_io; 1007 + b->legacy_io->read = pci_read_legacy_io; 1008 + b->legacy_io->write = pci_write_legacy_io; 1009 1009 /* See pci_create_attr() for motivation */ 1010 1010 b->legacy_io->llseek = pci_llseek_resource; 1011 1011 b->legacy_io->mmap = pci_mmap_legacy_io; ··· 1211 1211 } else { 1212 1212 sprintf(res_attr_name, "resource%d", num); 1213 1213 if (pci_resource_flags(pdev, num) & IORESOURCE_IO) { 1214 - res_attr->read_new = pci_read_resource_io; 1215 - res_attr->write_new = pci_write_resource_io; 1214 + res_attr->read = pci_read_resource_io; 1215 + res_attr->write = pci_write_resource_io; 1216 1216 if (arch_can_pci_mmap_io()) 1217 1217 res_attr->mmap = pci_mmap_resource_uc; 1218 1218 } else { ··· 1377 1377 } 1378 1378 1379 1379 static const struct attribute_group pci_dev_rom_attr_group = { 1380 - .bin_attrs_new = pci_dev_rom_attrs, 1380 + .bin_attrs = pci_dev_rom_attrs, 1381 1381 .is_bin_visible = pci_dev_rom_attr_is_visible, 1382 1382 .bin_size = pci_dev_rom_attr_bin_size, 1383 1383 };
+1 -1
drivers/pci/vpd.c
··· 336 336 } 337 337 338 338 const struct attribute_group pci_dev_vpd_attr_group = { 339 - .bin_attrs_new = vpd_attrs, 339 + .bin_attrs = vpd_attrs, 340 340 .is_bin_visible = vpd_attr_is_visible, 341 341 }; 342 342
+2 -2
drivers/pcmcia/cistpl.c
··· 1605 1605 const struct bin_attribute pccard_cis_attr = { 1606 1606 .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR }, 1607 1607 .size = 0x200, 1608 - .read_new = pccard_show_cis, 1609 - .write_new = pccard_store_cis, 1608 + .read = pccard_show_cis, 1609 + .write = pccard_store_cis, 1610 1610 };
+1 -1
drivers/platform/chrome/cros_ec_vbc.c
··· 108 108 109 109 static const struct attribute_group cros_ec_vbc_attr_group = { 110 110 .name = "vbc", 111 - .bin_attrs_new = cros_ec_vbc_bin_attrs, 111 + .bin_attrs = cros_ec_vbc_bin_attrs, 112 112 }; 113 113 114 114 static int cros_ec_vbc_probe(struct platform_device *pd)
+1 -1
drivers/platform/mellanox/mlxbf-bootctl.c
··· 993 993 994 994 static const struct bin_attribute mlxbf_bootctl_bootfifo_sysfs_attr = { 995 995 .attr = { .name = "bootfifo", .mode = 0400 }, 996 - .read_new = mlxbf_bootctl_bootfifo_read, 996 + .read = mlxbf_bootctl_bootfifo_read, 997 997 }; 998 998 999 999 static bool mlxbf_bootctl_guid_match(const guid_t *guid,
+2 -2
drivers/platform/x86/amd/hsmp/acpi.c
··· 509 509 510 510 static const struct bin_attribute hsmp_metric_tbl_attr = { 511 511 .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, 512 - .read_new = hsmp_metric_tbl_acpi_read, 512 + .read = hsmp_metric_tbl_acpi_read, 513 513 .size = sizeof(struct hsmp_metric_table), 514 514 }; 515 515 ··· 560 560 }; 561 561 562 562 static const struct attribute_group hsmp_attr_grp = { 563 - .bin_attrs_new = hsmp_attr_list, 563 + .bin_attrs = hsmp_attr_list, 564 564 .attrs = hsmp_dev_attr_list, 565 565 .is_bin_visible = hsmp_is_sock_attr_visible, 566 566 .is_visible = hsmp_is_sock_dev_attr_visible,
+2 -2
drivers/platform/x86/amd/hsmp/plat.c
··· 93 93 static const struct bin_attribute attr##index = { \ 94 94 .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ 95 95 .private = (void *)index, \ 96 - .read_new = hsmp_metric_tbl_plat_read, \ 96 + .read = hsmp_metric_tbl_plat_read, \ 97 97 .size = sizeof(struct hsmp_metric_table), \ 98 98 }; \ 99 99 static const struct bin_attribute _list[] = { \ ··· 112 112 113 113 #define HSMP_BIN_ATTR_GRP(index, _list, _name) \ 114 114 static const struct attribute_group sock##index##_attr_grp = { \ 115 - .bin_attrs_new = _list, \ 115 + .bin_attrs = _list, \ 116 116 .is_bin_visible = hsmp_is_sock_attr_visible, \ 117 117 .name = #_name, \ 118 118 }
+1 -1
drivers/platform/x86/dell/dcdbas.c
··· 662 662 663 663 static const struct attribute_group dcdbas_attr_group = { 664 664 .attrs = dcdbas_dev_attrs, 665 - .bin_attrs_new = dcdbas_bin_attrs, 665 + .bin_attrs = dcdbas_bin_attrs, 666 666 }; 667 667 668 668 static int dcdbas_probe(struct platform_device *dev)
+1 -1
drivers/platform/x86/dell/dell_rbu.c
··· 636 636 }; 637 637 638 638 static const struct attribute_group rbu_group = { 639 - .bin_attrs_new = rbu_bin_attrs, 639 + .bin_attrs = rbu_bin_attrs, 640 640 }; 641 641 642 642 static int __init dcdrbu_init(void)
+1 -1
drivers/platform/x86/intel/pmt/class.c
··· 340 340 entry->pmt_bin_attr.attr.name = ns->name; 341 341 entry->pmt_bin_attr.attr.mode = 0440; 342 342 entry->pmt_bin_attr.mmap = intel_pmt_mmap; 343 - entry->pmt_bin_attr.read_new = intel_pmt_read; 343 + entry->pmt_bin_attr.read = intel_pmt_read; 344 344 entry->pmt_bin_attr.size = entry->size; 345 345 346 346 ret = sysfs_create_bin_file(&dev->kobj, &entry->pmt_bin_attr);
+1 -1
drivers/platform/x86/intel/sdsi.c
··· 576 576 577 577 static const struct attribute_group sdsi_group = { 578 578 .attrs = sdsi_attrs, 579 - .bin_attrs_new = sdsi_bin_attrs, 579 + .bin_attrs = sdsi_bin_attrs, 580 580 .is_bin_visible = sdsi_battr_is_visible, 581 581 }; 582 582 __ATTRIBUTE_GROUPS(sdsi);
+1 -1
drivers/platform/x86/wmi-bmof.c
··· 46 46 47 47 static const struct attribute_group bmof_group = { 48 48 .bin_size = bmof_bin_size, 49 - .bin_attrs_new = bmof_attrs, 49 + .bin_attrs = bmof_attrs, 50 50 }; 51 51 52 52 static const struct attribute_group *bmof_groups[] = {
+1 -1
drivers/power/supply/ds2760_battery.c
··· 209 209 }; 210 210 211 211 static const struct attribute_group w1_ds2760_group = { 212 - .bin_attrs_new = w1_ds2760_bin_attrs, 212 + .bin_attrs = w1_ds2760_bin_attrs, 213 213 }; 214 214 215 215 static const struct attribute_group *w1_ds2760_groups[] = {
+5 -5
drivers/power/supply/ds2780_battery.c
··· 660 660 .mode = S_IRUGO | S_IWUSR, 661 661 }, 662 662 .size = DS2780_PARAM_EEPROM_SIZE, 663 - .read_new = ds2780_read_param_eeprom_bin, 664 - .write_new = ds2780_write_param_eeprom_bin, 663 + .read = ds2780_read_param_eeprom_bin, 664 + .write = ds2780_write_param_eeprom_bin, 665 665 }; 666 666 667 667 static ssize_t ds2780_read_user_eeprom_bin(struct file *filp, ··· 705 705 .mode = S_IRUGO | S_IWUSR, 706 706 }, 707 707 .size = DS2780_USER_EEPROM_SIZE, 708 - .read_new = ds2780_read_user_eeprom_bin, 709 - .write_new = ds2780_write_user_eeprom_bin, 708 + .read = ds2780_read_user_eeprom_bin, 709 + .write = ds2780_write_user_eeprom_bin, 710 710 }; 711 711 712 712 static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2780_get_pmod_enabled, ··· 734 734 735 735 static const struct attribute_group ds2780_sysfs_group = { 736 736 .attrs = ds2780_sysfs_attrs, 737 - .bin_attrs_new = ds2780_sysfs_bin_attrs, 737 + .bin_attrs = ds2780_sysfs_bin_attrs, 738 738 }; 739 739 740 740 static const struct attribute_group *ds2780_sysfs_groups[] = {
+5 -5
drivers/power/supply/ds2781_battery.c
··· 662 662 .mode = S_IRUGO | S_IWUSR, 663 663 }, 664 664 .size = DS2781_PARAM_EEPROM_SIZE, 665 - .read_new = ds2781_read_param_eeprom_bin, 666 - .write_new = ds2781_write_param_eeprom_bin, 665 + .read = ds2781_read_param_eeprom_bin, 666 + .write = ds2781_write_param_eeprom_bin, 667 667 }; 668 668 669 669 static ssize_t ds2781_read_user_eeprom_bin(struct file *filp, ··· 708 708 .mode = S_IRUGO | S_IWUSR, 709 709 }, 710 710 .size = DS2781_USER_EEPROM_SIZE, 711 - .read_new = ds2781_read_user_eeprom_bin, 712 - .write_new = ds2781_write_user_eeprom_bin, 711 + .read = ds2781_read_user_eeprom_bin, 712 + .write = ds2781_write_user_eeprom_bin, 713 713 }; 714 714 715 715 static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2781_get_pmod_enabled, ··· 737 737 738 738 static const struct attribute_group ds2781_sysfs_group = { 739 739 .attrs = ds2781_sysfs_attrs, 740 - .bin_attrs_new = ds2781_sysfs_bin_attrs, 740 + .bin_attrs = ds2781_sysfs_bin_attrs, 741 741 742 742 }; 743 743
+2 -2
drivers/power/supply/olpc_battery.c
··· 553 553 .mode = S_IRUGO, 554 554 }, 555 555 .size = EEPROM_SIZE, 556 - .read_new = olpc_bat_eeprom_read, 556 + .read = olpc_bat_eeprom_read, 557 557 }; 558 558 559 559 /* Allow userspace to see the specific error value pulled from the EC */ ··· 591 591 592 592 static const struct attribute_group olpc_bat_sysfs_group = { 593 593 .attrs = olpc_bat_sysfs_attrs, 594 - .bin_attrs_new = olpc_bat_sysfs_bin_attrs, 594 + .bin_attrs = olpc_bat_sysfs_bin_attrs, 595 595 }; 596 596 597 597 static const struct attribute_group *olpc_bat_sysfs_groups[] = {
+1 -1
drivers/ptp/ptp_ocp.c
··· 3938 3938 3939 3939 static const struct attribute_group art_timecard_group = { 3940 3940 .attrs = art_timecard_attrs, 3941 - .bin_attrs_new = bin_art_timecard_attrs, 3941 + .bin_attrs = bin_art_timecard_attrs, 3942 3942 }; 3943 3943 3944 3944 static const struct ocp_attr_group art_timecard_groups[] = {
+3 -3
drivers/rapidio/rio-sysfs.c
··· 247 247 .mode = S_IRUGO | S_IWUSR, 248 248 }, 249 249 .size = RIO_MAINT_SPACE_SZ, 250 - .read_new = rio_read_config, 251 - .write_new = rio_write_config, 250 + .read = rio_read_config, 251 + .write = rio_write_config, 252 252 }; 253 253 254 254 static const struct bin_attribute *const rio_dev_bin_attrs[] = { ··· 278 278 static const struct attribute_group rio_dev_group = { 279 279 .attrs = rio_dev_attrs, 280 280 .is_visible = rio_dev_is_attr_visible, 281 - .bin_attrs_new = rio_dev_bin_attrs, 281 + .bin_attrs = rio_dev_bin_attrs, 282 282 }; 283 283 284 284 const struct attribute_group *rio_dev_groups[] = {
+1 -1
drivers/s390/char/sclp_config.c
··· 142 142 .name = "event_data", 143 143 .mode = S_IWUSR, 144 144 }, 145 - .write_new = sysfs_ofb_data_write, 145 + .write = sysfs_ofb_data_write, 146 146 }; 147 147 #endif 148 148
+1 -1
drivers/s390/char/sclp_sd.c
··· 539 539 sysfs_bin_attr_init(&sd_file->data_attr); 540 540 sd_file->data_attr.attr.name = "data"; 541 541 sd_file->data_attr.attr.mode = 0444; 542 - sd_file->data_attr.read_new = data_read; 542 + sd_file->data_attr.read = data_read; 543 543 544 544 rc = sysfs_create_bin_file(&sd_file->kobj, &sd_file->data_attr); 545 545 if (rc) {
+1 -1
drivers/s390/cio/chp.c
··· 470 470 }; 471 471 static const struct attribute_group chp_attr_group = { 472 472 .attrs = chp_attrs, 473 - .bin_attrs_new = chp_bin_attrs, 473 + .bin_attrs = chp_bin_attrs, 474 474 }; 475 475 static const struct attribute_group *chp_attr_groups[] = { 476 476 &chp_attr_group,
+4 -4
drivers/s390/crypto/pkey_sysfs.c
··· 297 297 298 298 static const struct attribute_group protkey_attr_group = { 299 299 .name = "protkey", 300 - .bin_attrs_new = protkey_attrs, 300 + .bin_attrs = protkey_attrs, 301 301 }; 302 302 303 303 /* ··· 406 406 407 407 static const struct attribute_group ccadata_attr_group = { 408 408 .name = "ccadata", 409 - .bin_attrs_new = ccadata_attrs, 409 + .bin_attrs = ccadata_attrs, 410 410 }; 411 411 412 412 #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) ··· 520 520 521 521 static const struct attribute_group ccacipher_attr_group = { 522 522 .name = "ccacipher", 523 - .bin_attrs_new = ccacipher_attrs, 523 + .bin_attrs = ccacipher_attrs, 524 524 }; 525 525 526 526 /* ··· 635 635 636 636 static const struct attribute_group ep11_attr_group = { 637 637 .name = "ep11", 638 - .bin_attrs_new = ep11_attrs, 638 + .bin_attrs = ep11_attrs, 639 639 }; 640 640 641 641 const struct attribute_group *pkey_attr_groups[] = {
+2 -2
drivers/scsi/3w-sas.c
··· 122 122 .mode = S_IRUSR, 123 123 }, 124 124 .size = 0, 125 - .read_new = twl_sysfs_aen_read 125 + .read = twl_sysfs_aen_read 126 126 }; 127 127 128 128 /* This function returns driver compatibility info through sysfs */ ··· 153 153 .mode = S_IRUSR, 154 154 }, 155 155 .size = 0, 156 - .read_new = twl_sysfs_compat_info 156 + .read = twl_sysfs_compat_info 157 157 }; 158 158 159 159 /* Show some statistics about the card */
+3 -3
drivers/scsi/arcmsr/arcmsr_attr.c
··· 194 194 .mode = S_IRUSR , 195 195 }, 196 196 .size = ARCMSR_API_DATA_BUFLEN, 197 - .read_new = arcmsr_sysfs_iop_message_read, 197 + .read = arcmsr_sysfs_iop_message_read, 198 198 }; 199 199 200 200 static const struct bin_attribute arcmsr_sysfs_message_write_attr = { ··· 203 203 .mode = S_IWUSR, 204 204 }, 205 205 .size = ARCMSR_API_DATA_BUFLEN, 206 - .write_new = arcmsr_sysfs_iop_message_write, 206 + .write = arcmsr_sysfs_iop_message_write, 207 207 }; 208 208 209 209 static const struct bin_attribute arcmsr_sysfs_message_clear_attr = { ··· 212 212 .mode = S_IWUSR, 213 213 }, 214 214 .size = 1, 215 - .write_new = arcmsr_sysfs_iop_message_clear, 215 + .write = arcmsr_sysfs_iop_message_clear, 216 216 }; 217 217 218 218 int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
+3 -3
drivers/scsi/esas2r/esas2r_main.c
··· 215 215 .attr = \ 216 216 { .name = __stringify(_name), .mode = S_IRUSR | S_IWUSR }, \ 217 217 .size = 0, \ 218 - .read_new = read_ ## _name, \ 219 - .write_new = write_ ## _name } 218 + .read = read_ ## _name, \ 219 + .write = write_ ## _name } 220 220 221 221 ESAS2R_RW_BIN_ATTR(fw); 222 222 ESAS2R_RW_BIN_ATTR(fs); ··· 227 227 const struct bin_attribute bin_attr_default_nvram = { 228 228 .attr = { .name = "default_nvram", .mode = S_IRUGO }, 229 229 .size = 0, 230 - .read_new = read_default_nvram, 230 + .read = read_default_nvram, 231 231 .write = NULL 232 232 }; 233 233
+1 -1
drivers/scsi/ibmvscsi/ibmvfc.c
··· 3670 3670 .mode = S_IRUGO, 3671 3671 }, 3672 3672 .size = 0, 3673 - .read_new = ibmvfc_read_trace, 3673 + .read = ibmvfc_read_trace, 3674 3674 }; 3675 3675 #endif 3676 3676
+5 -5
drivers/scsi/ipr.c
··· 3389 3389 .mode = S_IRUGO, 3390 3390 }, 3391 3391 .size = 0, 3392 - .read_new = ipr_read_trace, 3392 + .read = ipr_read_trace, 3393 3393 }; 3394 3394 #endif 3395 3395 ··· 4140 4140 .mode = S_IRUGO | S_IWUSR, 4141 4141 }, 4142 4142 .size = 0, 4143 - .read_new = ipr_read_async_err_log, 4144 - .write_new = ipr_next_async_err_log 4143 + .read = ipr_read_async_err_log, 4144 + .write = ipr_next_async_err_log 4145 4145 }; 4146 4146 4147 4147 static struct attribute *ipr_ioa_attrs[] = { ··· 4391 4391 .mode = S_IRUSR | S_IWUSR, 4392 4392 }, 4393 4393 .size = 0, 4394 - .read_new = ipr_read_dump, 4395 - .write_new = ipr_write_dump 4394 + .read = ipr_read_dump, 4395 + .write = ipr_write_dump 4396 4396 }; 4397 4397 #else 4398 4398 static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
+4 -4
drivers/scsi/lpfc/lpfc_attr.c
··· 6420 6420 .mode = S_IRUSR | S_IWUSR, 6421 6421 }, 6422 6422 .size = 256, 6423 - .read_new = sysfs_ctlreg_read, 6424 - .write_new = sysfs_ctlreg_write, 6423 + .read = sysfs_ctlreg_read, 6424 + .write = sysfs_ctlreg_write, 6425 6425 }; 6426 6426 6427 6427 /** ··· 6478 6478 .mode = S_IRUSR | S_IWUSR, 6479 6479 }, 6480 6480 .size = MAILBOX_SYSFS_MAX, 6481 - .read_new = sysfs_mbox_read, 6482 - .write_new = sysfs_mbox_write, 6481 + .read = sysfs_mbox_read, 6482 + .write = sysfs_mbox_write, 6483 6483 }; 6484 6484 6485 6485 /**
+39 -48
drivers/scsi/lpfc/lpfc_debugfs.c
··· 2375 2375 lpfc_debugfs_dif_err_read(struct file *file, char __user *buf, 2376 2376 size_t nbytes, loff_t *ppos) 2377 2377 { 2378 - struct dentry *dent = file->f_path.dentry; 2379 2378 struct lpfc_hba *phba = file->private_data; 2379 + int kind = debugfs_get_aux_num(file); 2380 2380 char cbuf[32]; 2381 2381 uint64_t tmp = 0; 2382 2382 int cnt = 0; 2383 2383 2384 - if (dent == phba->debug_writeGuard) 2384 + if (kind == writeGuard) 2385 2385 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wgrd_cnt); 2386 - else if (dent == phba->debug_writeApp) 2386 + else if (kind == writeApp) 2387 2387 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wapp_cnt); 2388 - else if (dent == phba->debug_writeRef) 2388 + else if (kind == writeRef) 2389 2389 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_wref_cnt); 2390 - else if (dent == phba->debug_readGuard) 2390 + else if (kind == readGuard) 2391 2391 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rgrd_cnt); 2392 - else if (dent == phba->debug_readApp) 2392 + else if (kind == readApp) 2393 2393 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rapp_cnt); 2394 - else if (dent == phba->debug_readRef) 2394 + else if (kind == readRef) 2395 2395 cnt = scnprintf(cbuf, 32, "%u\n", phba->lpfc_injerr_rref_cnt); 2396 - else if (dent == phba->debug_InjErrNPortID) 2396 + else if (kind == InjErrNPortID) 2397 2397 cnt = scnprintf(cbuf, 32, "0x%06x\n", 2398 2398 phba->lpfc_injerr_nportid); 2399 - else if (dent == phba->debug_InjErrWWPN) { 2399 + else if (kind == InjErrWWPN) { 2400 2400 memcpy(&tmp, &phba->lpfc_injerr_wwpn, sizeof(struct lpfc_name)); 2401 2401 tmp = cpu_to_be64(tmp); 2402 2402 cnt = scnprintf(cbuf, 32, "0x%016llx\n", tmp); 2403 - } else if (dent == phba->debug_InjErrLBA) { 2403 + } else if (kind == InjErrLBA) { 2404 2404 if (phba->lpfc_injerr_lba == (sector_t)(-1)) 2405 2405 cnt = scnprintf(cbuf, 32, "off\n"); 2406 2406 else ··· 2417 2417 lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf, 2418 2418 size_t nbytes, loff_t *ppos) 2419 2419 { 2420 - struct dentry *dent = file->f_path.dentry; 2421 2420 struct lpfc_hba *phba = file->private_data; 2421 + int kind = debugfs_get_aux_num(file); 2422 2422 char dstbuf[33]; 2423 2423 uint64_t tmp = 0; 2424 2424 int size; ··· 2428 2428 if (copy_from_user(dstbuf, buf, size)) 2429 2429 return -EFAULT; 2430 2430 2431 - if (dent == phba->debug_InjErrLBA) { 2431 + if (kind == InjErrLBA) { 2432 2432 if ((dstbuf[0] == 'o') && (dstbuf[1] == 'f') && 2433 2433 (dstbuf[2] == 'f')) 2434 2434 tmp = (uint64_t)(-1); ··· 2437 2437 if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp))) 2438 2438 return -EINVAL; 2439 2439 2440 - if (dent == phba->debug_writeGuard) 2440 + if (kind == writeGuard) 2441 2441 phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp; 2442 - else if (dent == phba->debug_writeApp) 2442 + else if (kind == writeApp) 2443 2443 phba->lpfc_injerr_wapp_cnt = (uint32_t)tmp; 2444 - else if (dent == phba->debug_writeRef) 2444 + else if (kind == writeRef) 2445 2445 phba->lpfc_injerr_wref_cnt = (uint32_t)tmp; 2446 - else if (dent == phba->debug_readGuard) 2446 + else if (kind == readGuard) 2447 2447 phba->lpfc_injerr_rgrd_cnt = (uint32_t)tmp; 2448 - else if (dent == phba->debug_readApp) 2448 + else if (kind == readApp) 2449 2449 phba->lpfc_injerr_rapp_cnt = (uint32_t)tmp; 2450 - else if (dent == phba->debug_readRef) 2450 + else if (kind == readRef) 2451 2451 phba->lpfc_injerr_rref_cnt = (uint32_t)tmp; 2452 - else if (dent == phba->debug_InjErrLBA) 2452 + else if (kind == InjErrLBA) 2453 2453 phba->lpfc_injerr_lba = (sector_t)tmp; 2454 - else if (dent == phba->debug_InjErrNPortID) 2454 + else if (kind == InjErrNPortID) 2455 2455 phba->lpfc_injerr_nportid = (uint32_t)(tmp & Mask_DID); 2456 - else if (dent == phba->debug_InjErrWWPN) { 2456 + else if (kind == InjErrWWPN) { 2457 2457 tmp = cpu_to_be64(tmp); 2458 2458 memcpy(&phba->lpfc_injerr_wwpn, &tmp, sizeof(struct lpfc_name)); 2459 2459 } else ··· 6160 6160 phba->debug_dumpHostSlim = NULL; 6161 6161 6162 6162 /* Setup DIF Error Injections */ 6163 - snprintf(name, sizeof(name), "InjErrLBA"); 6164 6163 phba->debug_InjErrLBA = 6165 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6164 + debugfs_create_file_aux_num("InjErrLBA", 0644, 6166 6165 phba->hba_debugfs_root, 6167 - phba, &lpfc_debugfs_op_dif_err); 6166 + phba, InjErrLBA, &lpfc_debugfs_op_dif_err); 6168 6167 phba->lpfc_injerr_lba = LPFC_INJERR_LBA_OFF; 6169 6168 6170 - snprintf(name, sizeof(name), "InjErrNPortID"); 6171 6169 phba->debug_InjErrNPortID = 6172 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6170 + debugfs_create_file_aux_num("InjErrNPortID", 0644, 6173 6171 phba->hba_debugfs_root, 6174 - phba, &lpfc_debugfs_op_dif_err); 6172 + phba, InjErrNPortID, &lpfc_debugfs_op_dif_err); 6175 6173 6176 - snprintf(name, sizeof(name), "InjErrWWPN"); 6177 6174 phba->debug_InjErrWWPN = 6178 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6175 + debugfs_create_file_aux_num("InjErrWWPN", 0644, 6179 6176 phba->hba_debugfs_root, 6180 - phba, &lpfc_debugfs_op_dif_err); 6177 + phba, InjErrWWPN, &lpfc_debugfs_op_dif_err); 6181 6178 6182 - snprintf(name, sizeof(name), "writeGuardInjErr"); 6183 6179 phba->debug_writeGuard = 6184 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6180 + debugfs_create_file_aux_num("writeGuardInjErr", 0644, 6185 6181 phba->hba_debugfs_root, 6186 - phba, &lpfc_debugfs_op_dif_err); 6182 + phba, writeGuard, &lpfc_debugfs_op_dif_err); 6187 6183 6188 - snprintf(name, sizeof(name), "writeAppInjErr"); 6189 6184 phba->debug_writeApp = 6190 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6185 + debugfs_create_file_aux_num("writeAppInjErr", 0644, 6191 6186 phba->hba_debugfs_root, 6192 - phba, &lpfc_debugfs_op_dif_err); 6187 + phba, writeApp, &lpfc_debugfs_op_dif_err); 6193 6188 6194 - snprintf(name, sizeof(name), "writeRefInjErr"); 6195 6189 phba->debug_writeRef = 6196 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6190 + debugfs_create_file_aux_num("writeRefInjErr", 0644, 6197 6191 phba->hba_debugfs_root, 6198 - phba, &lpfc_debugfs_op_dif_err); 6192 + phba, writeRef, &lpfc_debugfs_op_dif_err); 6199 6193 6200 - snprintf(name, sizeof(name), "readGuardInjErr"); 6201 6194 phba->debug_readGuard = 6202 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6195 + debugfs_create_file_aux_num("readGuardInjErr", 0644, 6203 6196 phba->hba_debugfs_root, 6204 - phba, &lpfc_debugfs_op_dif_err); 6197 + phba, readGuard, &lpfc_debugfs_op_dif_err); 6205 6198 6206 - snprintf(name, sizeof(name), "readAppInjErr"); 6207 6199 phba->debug_readApp = 6208 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6200 + debugfs_create_file_aux_num("readAppInjErr", 0644, 6209 6201 phba->hba_debugfs_root, 6210 - phba, &lpfc_debugfs_op_dif_err); 6202 + phba, readApp, &lpfc_debugfs_op_dif_err); 6211 6203 6212 - snprintf(name, sizeof(name), "readRefInjErr"); 6213 6204 phba->debug_readRef = 6214 - debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, 6205 + debugfs_create_file_aux_num("readRefInjErr", 0644, 6215 6206 phba->hba_debugfs_root, 6216 - phba, &lpfc_debugfs_op_dif_err); 6207 + phba, readRef, &lpfc_debugfs_op_dif_err); 6217 6208 6218 6209 /* Setup slow ring trace */ 6219 6210 if (lpfc_debugfs_max_slow_ring_trc) {
+11
drivers/scsi/lpfc/lpfc_debugfs.h
··· 322 322 * discovery */ 323 323 #endif /* H_LPFC_DEBUG_FS */ 324 324 325 + enum { 326 + writeGuard = 1, 327 + writeApp, 328 + writeRef, 329 + readGuard, 330 + readApp, 331 + readRef, 332 + InjErrLBA, 333 + InjErrNPortID, 334 + InjErrWWPN, 335 + }; 325 336 326 337 /* 327 338 * Driver debug utility routines outside of debugfs. The debug utility
+2 -2
drivers/scsi/qedf/qedf_attr.c
··· 166 166 .mode = S_IRUSR | S_IWUSR, 167 167 }, 168 168 .size = 0, 169 - .read_new = qedf_sysfs_read_grcdump, 170 - .write_new = qedf_sysfs_write_grcdump, 169 + .read = qedf_sysfs_read_grcdump, 170 + .write = qedf_sysfs_write_grcdump, 171 171 }; 172 172 173 173 static struct sysfs_bin_attrs bin_file_entries[] = {
+14 -14
drivers/scsi/qla2xxx/qla_attr.c
··· 174 174 .mode = S_IRUSR | S_IWUSR, 175 175 }, 176 176 .size = 0, 177 - .read_new = qla2x00_sysfs_read_fw_dump, 178 - .write_new = qla2x00_sysfs_write_fw_dump, 177 + .read = qla2x00_sysfs_read_fw_dump, 178 + .write = qla2x00_sysfs_write_fw_dump, 179 179 }; 180 180 181 181 static ssize_t ··· 288 288 .mode = S_IRUSR | S_IWUSR, 289 289 }, 290 290 .size = 512, 291 - .read_new = qla2x00_sysfs_read_nvram, 292 - .write_new = qla2x00_sysfs_write_nvram, 291 + .read = qla2x00_sysfs_read_nvram, 292 + .write = qla2x00_sysfs_write_nvram, 293 293 }; 294 294 295 295 static ssize_t ··· 350 350 .mode = S_IRUSR | S_IWUSR, 351 351 }, 352 352 .size = 0, 353 - .read_new = qla2x00_sysfs_read_optrom, 354 - .write_new = qla2x00_sysfs_write_optrom, 353 + .read = qla2x00_sysfs_read_optrom, 354 + .write = qla2x00_sysfs_write_optrom, 355 355 }; 356 356 357 357 static ssize_t ··· 535 535 .mode = S_IWUSR, 536 536 }, 537 537 .size = 0, 538 - .write_new = qla2x00_sysfs_write_optrom_ctl, 538 + .write = qla2x00_sysfs_write_optrom_ctl, 539 539 }; 540 540 541 541 static ssize_t ··· 648 648 .mode = S_IRUSR | S_IWUSR, 649 649 }, 650 650 .size = 0, 651 - .read_new = qla2x00_sysfs_read_vpd, 652 - .write_new = qla2x00_sysfs_write_vpd, 651 + .read = qla2x00_sysfs_read_vpd, 652 + .write = qla2x00_sysfs_write_vpd, 653 653 }; 654 654 655 655 static ssize_t ··· 685 685 .mode = S_IRUSR | S_IWUSR, 686 686 }, 687 687 .size = SFP_DEV_SIZE, 688 - .read_new = qla2x00_sysfs_read_sfp, 688 + .read = qla2x00_sysfs_read_sfp, 689 689 }; 690 690 691 691 static ssize_t ··· 829 829 .mode = S_IWUSR, 830 830 }, 831 831 .size = 0, 832 - .write_new = qla2x00_sysfs_write_reset, 832 + .write = qla2x00_sysfs_write_reset, 833 833 }; 834 834 835 835 static ssize_t ··· 872 872 .mode = S_IWUSR, 873 873 }, 874 874 .size = 0, 875 - .write_new = qla2x00_issue_logo, 875 + .write = qla2x00_issue_logo, 876 876 }; 877 877 878 878 static ssize_t ··· 935 935 .mode = S_IRUSR, 936 936 }, 937 937 .size = 0, 938 - .read_new = qla2x00_sysfs_read_xgmac_stats, 938 + .read = qla2x00_sysfs_read_xgmac_stats, 939 939 }; 940 940 941 941 static ssize_t ··· 993 993 .mode = S_IRUSR, 994 994 }, 995 995 .size = 0, 996 - .read_new = qla2x00_sysfs_read_dcbx_tlv, 996 + .read = qla2x00_sysfs_read_dcbx_tlv, 997 997 }; 998 998 999 999 static struct sysfs_entry {
+2 -2
drivers/scsi/qla4xxx/ql4_attr.c
··· 110 110 .mode = S_IRUSR | S_IWUSR, 111 111 }, 112 112 .size = 0, 113 - .read_new = qla4_8xxx_sysfs_read_fw_dump, 114 - .write_new = qla4_8xxx_sysfs_write_fw_dump, 113 + .read = qla4_8xxx_sysfs_read_fw_dump, 114 + .write = qla4_8xxx_sysfs_write_fw_dump, 115 115 }; 116 116 117 117 static struct sysfs_entry {
+3 -3
drivers/scsi/scsi_sysfs.c
··· 917 917 static const struct bin_attribute dev_attr_vpd_##_page = { \ 918 918 .attr = {.name = __stringify(vpd_##_page), .mode = S_IRUGO }, \ 919 919 .size = 0, \ 920 - .read_new = show_vpd_##_page, \ 920 + .read = show_vpd_##_page, \ 921 921 }; 922 922 923 923 sdev_vpd_pg_attr(pg83); ··· 949 949 .mode = S_IRUGO, 950 950 }, 951 951 .size = 0, 952 - .read_new = show_inquiry, 952 + .read = show_inquiry, 953 953 }; 954 954 955 955 static ssize_t ··· 1362 1362 }; 1363 1363 static struct attribute_group scsi_sdev_attr_group = { 1364 1364 .attrs = scsi_sdev_attrs, 1365 - .bin_attrs_new = scsi_sdev_bin_attrs, 1365 + .bin_attrs = scsi_sdev_bin_attrs, 1366 1366 .is_visible = scsi_sdev_attr_is_visible, 1367 1367 .is_bin_visible = scsi_sdev_bin_attr_is_visible, 1368 1368 };
+1 -1
drivers/staging/greybus/camera.c
··· 1128 1128 1129 1129 static int gb_camera_debugfs_open(struct inode *inode, struct file *file) 1130 1130 { 1131 - file->private_data = (void *)debugfs_get_aux(file); 1131 + file->private_data = debugfs_get_aux(file); 1132 1132 return 0; 1133 1133 } 1134 1134
+10 -20
drivers/thermal/testing/command.c
··· 139 139 return ret; 140 140 } 141 141 142 - static ssize_t tt_command_process(struct dentry *dentry, const char __user *user_buf, 143 - size_t count) 142 + static ssize_t tt_command_process(char *s) 144 143 { 145 - char *buf __free(kfree); 146 144 char *arg; 147 145 int i; 148 146 149 - buf = kmalloc(count + 1, GFP_KERNEL); 150 - if (!buf) 151 - return -ENOMEM; 147 + strim(s); 152 148 153 - if (copy_from_user(buf, user_buf, count)) 154 - return -EFAULT; 155 - 156 - buf[count] = '\0'; 157 - strim(buf); 158 - 159 - arg = strstr(buf, ":"); 149 + arg = strchr(s, ':'); 160 150 if (arg) { 161 151 *arg = '\0'; 162 152 arg++; 163 153 } 164 154 165 155 for (i = 0; i < ARRAY_SIZE(tt_command_strings); i++) { 166 - if (!strcmp(buf, tt_command_strings[i])) 156 + if (!strcmp(s, tt_command_strings[i])) 167 157 return tt_command_exec(i, arg); 168 158 } 169 159 ··· 163 173 static ssize_t tt_command_write(struct file *file, const char __user *user_buf, 164 174 size_t count, loff_t *ppos) 165 175 { 166 - struct dentry *dentry = file->f_path.dentry; 176 + char buf[TT_COMMAND_SIZE]; 167 177 ssize_t ret; 168 178 169 179 if (*ppos) 170 180 return -EINVAL; 171 181 172 - if (count + 1 > TT_COMMAND_SIZE) 182 + if (count > TT_COMMAND_SIZE - 1) 173 183 return -E2BIG; 174 184 175 - ret = debugfs_file_get(dentry); 176 - if (unlikely(ret)) 177 - return ret; 185 + if (copy_from_user(buf, user_buf, count)) 186 + return -EFAULT; 187 + buf[count] = '\0'; 178 188 179 - ret = tt_command_process(dentry, user_buf, count); 189 + ret = tt_command_process(buf); 180 190 if (ret) 181 191 return ret; 182 192
+1 -1
drivers/usb/core/sysfs.c
··· 944 944 } 945 945 946 946 static const struct attribute_group dev_bin_attr_grp = { 947 - .bin_attrs_new = dev_bin_attrs, 947 + .bin_attrs = dev_bin_attrs, 948 948 .is_bin_visible = dev_bin_attrs_are_visible, 949 949 }; 950 950
+1 -1
drivers/usb/usbip/vudc_sysfs.c
··· 259 259 260 260 static const struct attribute_group vudc_attr_group = { 261 261 .attrs = dev_attrs, 262 - .bin_attrs_new = dev_bin_attrs, 262 + .bin_attrs = dev_bin_attrs, 263 263 }; 264 264 265 265 const struct attribute_group *vudc_groups[] = {
+2 -2
drivers/video/fbdev/aty/radeon_base.c
··· 2227 2227 .mode = 0444, 2228 2228 }, 2229 2229 .size = EDID_LENGTH, 2230 - .read_new = radeon_show_edid1, 2230 + .read = radeon_show_edid1, 2231 2231 }; 2232 2232 2233 2233 static const struct bin_attribute edid2_attr = { ··· 2236 2236 .mode = 0444, 2237 2237 }, 2238 2238 .size = EDID_LENGTH, 2239 - .read_new = radeon_show_edid2, 2239 + .read = radeon_show_edid2, 2240 2240 }; 2241 2241 2242 2242 static int radeonfb_pci_register(struct pci_dev *pdev,
+2 -2
drivers/video/fbdev/udlfb.c
··· 1482 1482 .attr.name = "edid", 1483 1483 .attr.mode = 0666, 1484 1484 .size = EDID_LENGTH, 1485 - .read_new = edid_show, 1486 - .write_new = edid_store 1485 + .read = edid_show, 1486 + .write = edid_store 1487 1487 }; 1488 1488 1489 1489 static const struct device_attribute fb_device_attrs[] = {
+4 -4
drivers/virt/coco/guest/tsm-mr.c
··· 209 209 210 210 if (tm->mrs[i].mr_flags & TSM_MR_F_READABLE) { 211 211 bap->attr.mode |= 0444; 212 - bap->read_new = tm_digest_read; 212 + bap->read = tm_digest_read; 213 213 } 214 214 215 215 if (tm->mrs[i].mr_flags & TSM_MR_F_WRITABLE) { 216 216 bap->attr.mode |= 0200; 217 - bap->write_new = tm_digest_write; 217 + bap->write = tm_digest_write; 218 218 } 219 219 220 220 bap->size = tm->mrs[i].mr_size; ··· 228 228 229 229 init_rwsem(&ctx->rwsem); 230 230 ctx->agrp.name = "measurements"; 231 - ctx->agrp.bin_attrs_new = no_free_ptr(attrs); 231 + ctx->agrp.bin_attrs = no_free_ptr(attrs); 232 232 ctx->tm = tm; 233 233 return &no_free_ptr(ctx)->agrp; 234 234 } ··· 244 244 void tsm_mr_free_attribute_group(const struct attribute_group *attr_grp) 245 245 { 246 246 if (!IS_ERR_OR_NULL(attr_grp)) { 247 - kfree(attr_grp->bin_attrs_new); 247 + kfree(attr_grp->bin_attrs); 248 248 kfree(container_of(attr_grp, struct tm_context, agrp)); 249 249 } 250 250 }
+2 -2
drivers/w1/slaves/w1_ds2406.c
··· 94 94 .mode = 0444, 95 95 }, 96 96 .size = 1, 97 - .read_new = w1_f12_read_state, 97 + .read = w1_f12_read_state, 98 98 }, 99 99 { 100 100 .attr = { ··· 102 102 .mode = 0664, 103 103 }, 104 104 .size = 1, 105 - .write_new = w1_f12_write_output, 105 + .write = w1_f12_write_output, 106 106 } 107 107 }; 108 108
+1 -1
drivers/w1/slaves/w1_ds2408.c
··· 328 328 }; 329 329 330 330 static const struct attribute_group w1_f29_group = { 331 - .bin_attrs_new = w1_f29_bin_attrs, 331 + .bin_attrs = w1_f29_bin_attrs, 332 332 }; 333 333 334 334 static const struct attribute_group *w1_f29_groups[] = {
+1 -1
drivers/w1/slaves/w1_ds2413.c
··· 137 137 }; 138 138 139 139 static const struct attribute_group w1_f3a_group = { 140 - .bin_attrs_new = w1_f3a_bin_attrs, 140 + .bin_attrs = w1_f3a_bin_attrs, 141 141 }; 142 142 143 143 static const struct attribute_group *w1_f3a_groups[] = {
+1 -1
drivers/w1/slaves/w1_ds2430.c
··· 271 271 }; 272 272 273 273 static const struct attribute_group w1_f14_group = { 274 - .bin_attrs_new = w1_f14_bin_attrs, 274 + .bin_attrs = w1_f14_bin_attrs, 275 275 }; 276 276 277 277 static const struct attribute_group *w1_f14_groups[] = {
+1 -1
drivers/w1/slaves/w1_ds2431.c
··· 270 270 }; 271 271 272 272 static const struct attribute_group w1_f2d_group = { 273 - .bin_attrs_new = w1_f2d_bin_attrs, 273 + .bin_attrs = w1_f2d_bin_attrs, 274 274 }; 275 275 276 276 static const struct attribute_group *w1_f2d_groups[] = {
+6 -6
drivers/w1/slaves/w1_ds2433.c
··· 276 276 277 277 static const struct bin_attribute bin_attr_f23_eeprom = { 278 278 .attr = { .name = "eeprom", .mode = 0644 }, 279 - .read_new = eeprom_read, 280 - .write_new = eeprom_write, 279 + .read = eeprom_read, 280 + .write = eeprom_write, 281 281 .size = W1_EEPROM_DS2433_SIZE, 282 282 }; 283 283 284 284 static const struct bin_attribute bin_attr_f43_eeprom = { 285 285 .attr = { .name = "eeprom", .mode = 0644 }, 286 - .read_new = eeprom_read, 287 - .write_new = eeprom_write, 286 + .read = eeprom_read, 287 + .write = eeprom_write, 288 288 .size = W1_EEPROM_DS28EC20_SIZE, 289 289 }; 290 290 ··· 294 294 }; 295 295 296 296 static const struct attribute_group w1_f23_group = { 297 - .bin_attrs_new = w1_f23_bin_attributes, 297 + .bin_attrs = w1_f23_bin_attributes, 298 298 }; 299 299 300 300 static const struct attribute_group *w1_f23_groups[] = { ··· 308 308 }; 309 309 310 310 static const struct attribute_group w1_f43_group = { 311 - .bin_attrs_new = w1_f43_bin_attributes, 311 + .bin_attrs = w1_f43_bin_attributes, 312 312 }; 313 313 314 314 static const struct attribute_group *w1_f43_groups[] = {
+1 -1
drivers/w1/slaves/w1_ds2438.c
··· 492 492 }; 493 493 494 494 static const struct attribute_group w1_ds2438_group = { 495 - .bin_attrs_new = w1_ds2438_bin_attrs, 495 + .bin_attrs = w1_ds2438_bin_attrs, 496 496 }; 497 497 498 498 static const struct attribute_group *w1_ds2438_groups[] = {
+1 -1
drivers/w1/slaves/w1_ds2780.c
··· 103 103 }; 104 104 105 105 static const struct attribute_group w1_ds2780_group = { 106 - .bin_attrs_new = w1_ds2780_bin_attrs, 106 + .bin_attrs = w1_ds2780_bin_attrs, 107 107 }; 108 108 109 109 static const struct attribute_group *w1_ds2780_groups[] = {
+1 -1
drivers/w1/slaves/w1_ds2781.c
··· 100 100 }; 101 101 102 102 static const struct attribute_group w1_ds2781_group = { 103 - .bin_attrs_new = w1_ds2781_bin_attrs, 103 + .bin_attrs = w1_ds2781_bin_attrs, 104 104 }; 105 105 106 106 static const struct attribute_group *w1_ds2781_groups[] = {
+2 -2
drivers/w1/slaves/w1_ds2805.c
··· 267 267 .mode = 0644, 268 268 }, 269 269 .size = W1_F0D_EEPROM_SIZE, 270 - .read_new = w1_f0d_read_bin, 271 - .write_new = w1_f0d_write_bin, 270 + .read = w1_f0d_read_bin, 271 + .write = w1_f0d_write_bin, 272 272 }; 273 273 274 274 static int w1_f0d_add_slave(struct w1_slave *sl)
+1 -1
drivers/w1/slaves/w1_ds28e04.c
··· 371 371 372 372 static const struct attribute_group w1_f1C_group = { 373 373 .attrs = w1_f1C_attrs, 374 - .bin_attrs_new = w1_f1C_bin_attrs, 374 + .bin_attrs = w1_f1C_bin_attrs, 375 375 }; 376 376 377 377 static const struct attribute_group *w1_f1C_groups[] = {
+1 -1
drivers/w1/w1.c
··· 149 149 }; 150 150 151 151 static const struct attribute_group w1_slave_default_group = { 152 - .bin_attrs_new = w1_slave_bin_attrs, 152 + .bin_attrs = w1_slave_bin_attrs, 153 153 }; 154 154 155 155 static const struct attribute_group *w1_slave_default_groups[] = {
+2 -2
drivers/zorro/zorro-sysfs.c
··· 104 104 .mode = S_IRUGO, 105 105 }, 106 106 .size = sizeof(struct ConfigDev), 107 - .read_new = zorro_read_config, 107 + .read = zorro_read_config, 108 108 }; 109 109 110 110 static const struct bin_attribute *const zorro_device_bin_attrs[] = { ··· 114 114 115 115 static const struct attribute_group zorro_device_attr_group = { 116 116 .attrs = zorro_device_attrs, 117 - .bin_attrs_new = zorro_device_bin_attrs, 117 + .bin_attrs = zorro_device_bin_attrs, 118 118 }; 119 119 120 120 const struct attribute_group *zorro_device_attribute_groups[] = {
+39 -50
fs/debugfs/file.c
··· 47 47 48 48 #define F_DENTRY(filp) ((filp)->f_path.dentry) 49 49 50 - const void *debugfs_get_aux(const struct file *file) 50 + void *debugfs_get_aux(const struct file *file) 51 51 { 52 52 return DEBUGFS_I(file_inode(file))->aux; 53 53 } 54 54 EXPORT_SYMBOL_GPL(debugfs_get_aux); 55 - 56 - const struct file_operations *debugfs_real_fops(const struct file *filp) 57 - { 58 - struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata; 59 - 60 - if (!fsd) { 61 - /* 62 - * Urgh, we've been called w/o a protecting 63 - * debugfs_file_get(). 64 - */ 65 - WARN_ON(1); 66 - return NULL; 67 - } 68 - 69 - return fsd->real_fops; 70 - } 71 - EXPORT_SYMBOL_GPL(debugfs_real_fops); 72 55 73 56 enum dbgfs_get_mode { 74 57 DBGFS_GET_ALREADY, ··· 285 302 static int open_proxy_open(struct inode *inode, struct file *filp) 286 303 { 287 304 struct dentry *dentry = F_DENTRY(filp); 288 - const struct file_operations *real_fops = NULL; 305 + const struct file_operations *real_fops = DEBUGFS_I(inode)->real_fops; 289 306 int r; 290 307 291 308 r = __debugfs_file_get(dentry, DBGFS_GET_REGULAR); 292 309 if (r) 293 310 return r == -EIO ? -ENOENT : r; 294 - 295 - real_fops = debugfs_real_fops(filp); 296 311 297 312 r = debugfs_locked_down(inode, filp, real_fops); 298 313 if (r) ··· 333 352 { \ 334 353 struct dentry *dentry = F_DENTRY(filp); \ 335 354 struct debugfs_fsdata *fsd = dentry->d_fsdata; \ 336 - const struct file_operations *real_fops; \ 337 355 ret_type r; \ 338 356 \ 339 357 if (!(fsd->methods & bit)) \ ··· 340 360 r = debugfs_file_get(dentry); \ 341 361 if (unlikely(r)) \ 342 362 return r; \ 343 - real_fops = debugfs_real_fops(filp); \ 344 - r = real_fops->name(args); \ 363 + r = fsd->real_fops->name(args); \ 345 364 debugfs_file_put(dentry); \ 346 365 return r; \ 347 366 } 348 367 349 - #define FULL_PROXY_FUNC_BOTH(name, ret_type, filp, proto, args, bit, ret) \ 350 - static ret_type full_proxy_ ## name(proto) \ 368 + #define SHORT_PROXY_FUNC(name, ret_type, filp, proto, args, bit, ret) \ 369 + static ret_type short_proxy_ ## name(proto) \ 351 370 { \ 352 371 struct dentry *dentry = F_DENTRY(filp); \ 353 372 struct debugfs_fsdata *fsd = dentry->d_fsdata; \ ··· 357 378 r = debugfs_file_get(dentry); \ 358 379 if (unlikely(r)) \ 359 380 return r; \ 360 - if (fsd->real_fops) \ 361 - r = fsd->real_fops->name(args); \ 362 - else \ 363 - r = fsd->short_fops->name(args); \ 381 + r = fsd->short_fops->name(args); \ 364 382 debugfs_file_put(dentry); \ 365 383 return r; \ 366 384 } 367 385 368 - FULL_PROXY_FUNC_BOTH(llseek, loff_t, filp, 369 - PROTO(struct file *filp, loff_t offset, int whence), 370 - ARGS(filp, offset, whence), HAS_LSEEK, -ESPIPE); 386 + SHORT_PROXY_FUNC(llseek, loff_t, filp, 387 + PROTO(struct file *filp, loff_t offset, int whence), 388 + ARGS(filp, offset, whence), HAS_LSEEK, -ESPIPE); 371 389 372 - FULL_PROXY_FUNC_BOTH(read, ssize_t, filp, 373 - PROTO(struct file *filp, char __user *buf, size_t size, 374 - loff_t *ppos), 375 - ARGS(filp, buf, size, ppos), HAS_READ, -EINVAL); 390 + FULL_PROXY_FUNC(llseek, loff_t, filp, 391 + PROTO(struct file *filp, loff_t offset, int whence), 392 + ARGS(filp, offset, whence), HAS_LSEEK, -ESPIPE); 376 393 377 - FULL_PROXY_FUNC_BOTH(write, ssize_t, filp, 378 - PROTO(struct file *filp, const char __user *buf, 379 - size_t size, loff_t *ppos), 380 - ARGS(filp, buf, size, ppos), HAS_WRITE, -EINVAL); 394 + SHORT_PROXY_FUNC(read, ssize_t, filp, 395 + PROTO(struct file *filp, char __user *buf, size_t size, 396 + loff_t *ppos), 397 + ARGS(filp, buf, size, ppos), HAS_READ, -EINVAL); 398 + 399 + FULL_PROXY_FUNC(read, ssize_t, filp, 400 + PROTO(struct file *filp, char __user *buf, size_t size, 401 + loff_t *ppos), 402 + ARGS(filp, buf, size, ppos), HAS_READ, -EINVAL); 403 + 404 + SHORT_PROXY_FUNC(write, ssize_t, filp, 405 + PROTO(struct file *filp, const char __user *buf, 406 + size_t size, loff_t *ppos), 407 + ARGS(filp, buf, size, ppos), HAS_WRITE, -EINVAL); 408 + 409 + FULL_PROXY_FUNC(write, ssize_t, filp, 410 + PROTO(struct file *filp, const char __user *buf, 411 + size_t size, loff_t *ppos), 412 + ARGS(filp, buf, size, ppos), HAS_WRITE, -EINVAL); 381 413 382 414 FULL_PROXY_FUNC(unlocked_ioctl, long, filp, 383 415 PROTO(struct file *filp, unsigned int cmd, unsigned long arg), ··· 400 410 struct dentry *dentry = F_DENTRY(filp); 401 411 struct debugfs_fsdata *fsd = dentry->d_fsdata; 402 412 __poll_t r = 0; 403 - const struct file_operations *real_fops; 404 413 405 414 if (!(fsd->methods & HAS_POLL)) 406 415 return DEFAULT_POLLMASK; 407 416 if (debugfs_file_get(dentry)) 408 417 return EPOLLHUP; 409 418 410 - real_fops = debugfs_real_fops(filp); 411 - r = real_fops->poll(filp, wait); 419 + r = fsd->real_fops->poll(filp, wait); 412 420 debugfs_file_put(dentry); 413 421 return r; 414 422 } 415 423 416 - static int full_proxy_release(struct inode *inode, struct file *filp) 424 + static int full_proxy_release(struct inode *inode, struct file *file) 417 425 { 418 - const struct file_operations *real_fops = debugfs_real_fops(filp); 426 + struct debugfs_fsdata *fsd = F_DENTRY(file)->d_fsdata; 427 + const struct file_operations *real_fops = fsd->real_fops; 419 428 int r = 0; 420 429 421 430 /* ··· 424 435 * ->i_private is still being meaningful here. 425 436 */ 426 437 if (real_fops->release) 427 - r = real_fops->release(inode, filp); 438 + r = real_fops->release(inode, file); 428 439 429 440 fops_put(real_fops); 430 441 return r; ··· 506 517 507 518 const struct file_operations debugfs_full_short_proxy_file_operations = { 508 519 .open = full_proxy_open_short, 509 - .llseek = full_proxy_llseek, 510 - .read = full_proxy_read, 511 - .write = full_proxy_write, 520 + .llseek = short_proxy_llseek, 521 + .read = short_proxy_read, 522 + .write = short_proxy_write, 512 523 }; 513 524 514 525 ssize_t debugfs_attr_read(struct file *file, char __user *buf,
+1 -1
fs/debugfs/inode.c
··· 444 444 proxy_fops = &debugfs_noop_file_operations; 445 445 inode->i_fop = proxy_fops; 446 446 DEBUGFS_I(inode)->raw = real_fops; 447 - DEBUGFS_I(inode)->aux = aux; 447 + DEBUGFS_I(inode)->aux = (void *)aux; 448 448 449 449 d_instantiate(dentry, inode); 450 450 fsnotify_create(d_inode(dentry->d_parent), dentry);
+1 -1
fs/debugfs/internal.h
··· 19 19 const struct debugfs_short_fops *short_fops; 20 20 debugfs_automount_t automount; 21 21 }; 22 - const void *aux; 22 + void *aux; 23 23 }; 24 24 25 25 static inline struct debugfs_inode_info *DEBUGFS_I(struct inode *inode)
-4
fs/resctrl/pseudo_lock.c
··· 764 764 if (ret == 0) { 765 765 if (sel != 1 && sel != 2 && sel != 3) 766 766 return -EINVAL; 767 - ret = debugfs_file_get(file->f_path.dentry); 768 - if (ret) 769 - return ret; 770 767 ret = pseudo_lock_measure_cycles(rdtgrp, sel); 771 768 if (ret == 0) 772 769 ret = count; 773 - debugfs_file_put(file->f_path.dentry); 774 770 } 775 771 776 772 return ret;
+5 -5
fs/sysfs/file.c
··· 83 83 static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf, 84 84 size_t count, loff_t pos) 85 85 { 86 - struct bin_attribute *battr = of->kn->priv; 86 + const struct bin_attribute *battr = of->kn->priv; 87 87 struct kobject *kobj = sysfs_file_kobj(of->kn); 88 88 loff_t size = file_inode(of->file)->i_size; 89 89 ··· 149 149 static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf, 150 150 size_t count, loff_t pos) 151 151 { 152 - struct bin_attribute *battr = of->kn->priv; 152 + const struct bin_attribute *battr = of->kn->priv; 153 153 struct kobject *kobj = sysfs_file_kobj(of->kn); 154 154 loff_t size = file_inode(of->file)->i_size; 155 155 ··· 173 173 static int sysfs_kf_bin_mmap(struct kernfs_open_file *of, 174 174 struct vm_area_struct *vma) 175 175 { 176 - struct bin_attribute *battr = of->kn->priv; 176 + const struct bin_attribute *battr = of->kn->priv; 177 177 struct kobject *kobj = sysfs_file_kobj(of->kn); 178 178 179 179 return battr->mmap(of->file, kobj, battr, vma); ··· 182 182 static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset, 183 183 int whence) 184 184 { 185 - struct bin_attribute *battr = of->kn->priv; 185 + const struct bin_attribute *battr = of->kn->priv; 186 186 struct kobject *kobj = sysfs_file_kobj(of->kn); 187 187 188 188 if (battr->llseek) ··· 193 193 194 194 static int sysfs_kf_bin_open(struct kernfs_open_file *of) 195 195 { 196 - struct bin_attribute *battr = of->kn->priv; 196 + const struct bin_attribute *battr = of->kn->priv; 197 197 198 198 if (battr->f_mapping) 199 199 of->file->f_mapping = battr->f_mapping();
+3
include/linux/container_of.h
··· 14 14 * @member: the name of the member within the struct. 15 15 * 16 16 * WARNING: any const qualifier of @ptr is lost. 17 + * Do not use container_of() in new code. 17 18 */ 18 19 #define container_of(ptr, type, member) ({ \ 19 20 void *__mptr = (void *)(ptr); \ ··· 29 28 * @ptr: the pointer to the member 30 29 * @type: the type of the container struct this is embedded in. 31 30 * @member: the name of the member within the struct. 31 + * 32 + * Always prefer container_of_const() instead of container_of() in new code. 32 33 */ 33 34 #define container_of_const(ptr, type, member) \ 34 35 _Generic(ptr, \
+1 -3
include/linux/debugfs.h
··· 162 162 163 163 void debugfs_lookup_and_remove(const char *name, struct dentry *parent); 164 164 165 - const struct file_operations *debugfs_real_fops(const struct file *filp); 166 - const void *debugfs_get_aux(const struct file *file); 165 + void *debugfs_get_aux(const struct file *file); 167 166 168 167 int debugfs_file_get(struct dentry *dentry); 169 168 void debugfs_file_put(struct dentry *dentry); ··· 328 329 struct dentry *parent) 329 330 { } 330 331 331 - const struct file_operations *debugfs_real_fops(const struct file *filp); 332 332 void *debugfs_get_aux(const struct file *file); 333 333 334 334 static inline int debugfs_file_get(struct dentry *dentry)
+5
include/linux/device.h
··· 1202 1202 void device_links_supplier_sync_state_resume(void); 1203 1203 void device_link_wait_removal(void); 1204 1204 1205 + static inline bool device_link_test(const struct device_link *link, u32 flags) 1206 + { 1207 + return !!(link->flags & flags); 1208 + } 1209 + 1205 1210 /* Create alias, so I can be autoloaded. */ 1206 1211 #define MODULE_ALIAS_CHARDEV(major,minor) \ 1207 1212 MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))
+4 -3
include/linux/property.h
··· 17 17 #include <linux/fwnode.h> 18 18 #include <linux/stddef.h> 19 19 #include <linux/types.h> 20 + #include <linux/util_macros.h> 20 21 21 22 struct device; 22 23 ··· 170 169 171 170 #define fwnode_for_each_named_child_node(fwnode, child, name) \ 172 171 fwnode_for_each_child_node(fwnode, child) \ 173 - if (!fwnode_name_eq(child, name)) { } else 172 + for_each_if(fwnode_name_eq(child, name)) 174 173 175 174 #define fwnode_for_each_available_child_node(fwnode, child) \ 176 175 for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\ ··· 185 184 186 185 #define device_for_each_named_child_node(dev, child, name) \ 187 186 device_for_each_child_node(dev, child) \ 188 - if (!fwnode_name_eq(child, name)) { } else 187 + for_each_if(fwnode_name_eq(child, name)) 189 188 190 189 #define device_for_each_child_node_scoped(dev, child) \ 191 190 for (struct fwnode_handle *child __free(fwnode_handle) = \ ··· 194 193 195 194 #define device_for_each_named_child_node_scoped(dev, child, name) \ 196 195 device_for_each_child_node_scoped(dev, child) \ 197 - if (!fwnode_name_eq(child, name)) { } else 196 + for_each_if(fwnode_name_eq(child, name)) 198 197 199 198 struct fwnode_handle *fwnode_get_named_child_node(const struct fwnode_handle *fwnode, 200 199 const char *childname);
+1 -1
kernel/bpf/btf.c
··· 8183 8183 attr->attr.mode = 0444; 8184 8184 attr->size = btf->data_size; 8185 8185 attr->private = btf->data; 8186 - attr->read_new = sysfs_bin_attr_simple_read; 8186 + attr->read = sysfs_bin_attr_simple_read; 8187 8187 8188 8188 err = sysfs_create_bin_file(btf_kobj, attr); 8189 8189 if (err) {
+1 -1
kernel/bpf/sysfs_btf.c
··· 45 45 46 46 static struct bin_attribute bin_attr_btf_vmlinux __ro_after_init = { 47 47 .attr = { .name = "vmlinux", .mode = 0444, }, 48 - .read_new = sysfs_bin_attr_simple_read, 48 + .read = sysfs_bin_attr_simple_read, 49 49 .mmap = btf_sysfs_vmlinux_mmap, 50 50 }; 51 51
+7 -7
kernel/module/sysfs.c
··· 56 56 { 57 57 const struct bin_attribute *const *bin_attr; 58 58 59 - for (bin_attr = sect_attrs->grp.bin_attrs_new; *bin_attr; bin_attr++) 59 + for (bin_attr = sect_attrs->grp.bin_attrs; *bin_attr; bin_attr++) 60 60 kfree((*bin_attr)->attr.name); 61 - kfree(sect_attrs->grp.bin_attrs_new); 61 + kfree(sect_attrs->grp.bin_attrs); 62 62 kfree(sect_attrs); 63 63 } 64 64 ··· 86 86 87 87 /* Setup section attributes. */ 88 88 sect_attrs->grp.name = "sections"; 89 - sect_attrs->grp.bin_attrs_new = gattr; 89 + sect_attrs->grp.bin_attrs = gattr; 90 90 91 91 sattr = &sect_attrs->attrs[0]; 92 92 for (i = 0; i < info->hdr->e_shnum; i++) { ··· 101 101 ret = -ENOMEM; 102 102 goto out; 103 103 } 104 - sattr->read_new = module_sect_read; 104 + sattr->read = module_sect_read; 105 105 sattr->private = (void *)sec->sh_addr; 106 106 sattr->size = MODULE_SECT_READ_SIZE; 107 107 sattr->attr.mode = 0400; ··· 144 144 145 145 static void free_notes_attrs(struct module_notes_attrs *notes_attrs) 146 146 { 147 - kfree(notes_attrs->grp.bin_attrs_new); 147 + kfree(notes_attrs->grp.bin_attrs); 148 148 kfree(notes_attrs); 149 149 } 150 150 ··· 178 178 } 179 179 180 180 notes_attrs->grp.name = "notes"; 181 - notes_attrs->grp.bin_attrs_new = gattr; 181 + notes_attrs->grp.bin_attrs = gattr; 182 182 183 183 nattr = &notes_attrs->attrs[0]; 184 184 for (loaded = i = 0; i < info->hdr->e_shnum; ++i) { ··· 190 190 nattr->attr.mode = 0444; 191 191 nattr->size = info->sechdrs[i].sh_size; 192 192 nattr->private = (void *)info->sechdrs[i].sh_addr; 193 - nattr->read_new = sysfs_bin_attr_simple_read; 193 + nattr->read = sysfs_bin_attr_simple_read; 194 194 *(gattr++) = nattr++; 195 195 } 196 196 ++loaded;
+1 -1
mm/page_idle.c
··· 208 208 }; 209 209 210 210 static const struct attribute_group page_idle_attr_group = { 211 - .bin_attrs_new = page_idle_bin_attrs, 211 + .bin_attrs = page_idle_bin_attrs, 212 212 .name = "page_idle", 213 213 }; 214 214
+5 -3
mm/vmscan.c
··· 5428 5428 static int lru_gen_seq_show(struct seq_file *m, void *v) 5429 5429 { 5430 5430 unsigned long seq; 5431 - bool full = !debugfs_real_fops(m->file)->write; 5431 + bool full = debugfs_get_aux_num(m->file); 5432 5432 struct lruvec *lruvec = v; 5433 5433 struct lru_gen_folio *lrugen = &lruvec->lrugen; 5434 5434 int nid = lruvec_pgdat(lruvec)->node_id; ··· 5764 5764 if (sysfs_create_group(mm_kobj, &lru_gen_attr_group)) 5765 5765 pr_err("lru_gen: failed to create sysfs group\n"); 5766 5766 5767 - debugfs_create_file("lru_gen", 0644, NULL, NULL, &lru_gen_rw_fops); 5768 - debugfs_create_file("lru_gen_full", 0444, NULL, NULL, &lru_gen_ro_fops); 5767 + debugfs_create_file_aux_num("lru_gen", 0644, NULL, NULL, 1, 5768 + &lru_gen_rw_fops); 5769 + debugfs_create_file_aux_num("lru_gen_full", 0444, NULL, NULL, 0, 5770 + &lru_gen_ro_fops); 5769 5771 5770 5772 return 0; 5771 5773 };
+1 -1
net/bridge/br_sysfs_br.c
··· 1026 1026 static const struct bin_attribute bridge_forward = { 1027 1027 .attr = { .name = SYSFS_BRIDGE_FDB, 1028 1028 .mode = 0444, }, 1029 - .read_new = brforward_read, 1029 + .read = brforward_read, 1030 1030 }; 1031 1031 1032 1032 /*
+2
rust/bindings/bindings_helper.h
··· 28 28 */ 29 29 #include <linux/hrtimer_types.h> 30 30 31 + #include <linux/acpi.h> 31 32 #include <drm/drm_device.h> 32 33 #include <drm/drm_drv.h> 33 34 #include <drm/drm_file.h> ··· 53 52 #include <linux/file.h> 54 53 #include <linux/firmware.h> 55 54 #include <linux/fs.h> 55 + #include <linux/ioport.h> 56 56 #include <linux/jiffies.h> 57 57 #include <linux/jump_label.h> 58 58 #include <linux/mdio.h>
-10
rust/helpers/auxiliary.c
··· 2 2 3 3 #include <linux/auxiliary_bus.h> 4 4 5 - void rust_helper_auxiliary_set_drvdata(struct auxiliary_device *adev, void *data) 6 - { 7 - auxiliary_set_drvdata(adev, data); 8 - } 9 - 10 - void *rust_helper_auxiliary_get_drvdata(struct auxiliary_device *adev) 11 - { 12 - return auxiliary_get_drvdata(adev); 13 - } 14 - 15 5 void rust_helper_auxiliary_device_uninit(struct auxiliary_device *adev) 16 6 { 17 7 return auxiliary_device_uninit(adev);
+17
rust/helpers/device.c
··· 8 8 { 9 9 return devm_add_action(dev, action, data); 10 10 } 11 + 12 + int rust_helper_devm_add_action_or_reset(struct device *dev, 13 + void (*action)(void *), 14 + void *data) 15 + { 16 + return devm_add_action_or_reset(dev, action, data); 17 + } 18 + 19 + void *rust_helper_dev_get_drvdata(const struct device *dev) 20 + { 21 + return dev_get_drvdata(dev); 22 + } 23 + 24 + void rust_helper_dev_set_drvdata(struct device *dev, void *data) 25 + { 26 + dev_set_drvdata(dev, data); 27 + }
+5
rust/helpers/dma.c
··· 14 14 { 15 15 dma_free_attrs(dev, size, cpu_addr, dma_handle, attrs); 16 16 } 17 + 18 + int rust_helper_dma_set_mask_and_coherent(struct device *dev, u64 mask) 19 + { 20 + return dma_set_mask_and_coherent(dev, mask); 21 + }
+2
rust/helpers/helpers.c
··· 28 28 #include "kunit.c" 29 29 #include "mm.c" 30 30 #include "mutex.c" 31 + #include "of.c" 31 32 #include "page.c" 32 33 #include "platform.c" 33 34 #include "pci.c" 34 35 #include "pid_namespace.c" 35 36 #include "poll.c" 37 + #include "property.c" 36 38 #include "rbtree.c" 37 39 #include "regulator.c" 38 40 #include "rcu.c"
+41
rust/helpers/io.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 3 #include <linux/io.h> 4 + #include <linux/ioport.h> 4 5 5 6 void __iomem *rust_helper_ioremap(phys_addr_t offset, size_t size) 6 7 { 7 8 return ioremap(offset, size); 9 + } 10 + 11 + void __iomem *rust_helper_ioremap_np(phys_addr_t offset, size_t size) 12 + { 13 + return ioremap_np(offset, size); 8 14 } 9 15 10 16 void rust_helper_iounmap(void __iomem *addr) ··· 105 99 writeq_relaxed(value, addr); 106 100 } 107 101 #endif 102 + 103 + resource_size_t rust_helper_resource_size(struct resource *res) 104 + { 105 + return resource_size(res); 106 + } 107 + 108 + struct resource *rust_helper_request_mem_region(resource_size_t start, 109 + resource_size_t n, 110 + const char *name) 111 + { 112 + return request_mem_region(start, n, name); 113 + } 114 + 115 + void rust_helper_release_mem_region(resource_size_t start, resource_size_t n) 116 + { 117 + release_mem_region(start, n); 118 + } 119 + 120 + struct resource *rust_helper_request_region(resource_size_t start, 121 + resource_size_t n, const char *name) 122 + { 123 + return request_region(start, n, name); 124 + } 125 + 126 + struct resource *rust_helper_request_muxed_region(resource_size_t start, 127 + resource_size_t n, 128 + const char *name) 129 + { 130 + return request_muxed_region(start, n, name); 131 + } 132 + 133 + void rust_helper_release_region(resource_size_t start, resource_size_t n) 134 + { 135 + release_region(start, n); 136 + }
+8
rust/helpers/of.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/of.h> 4 + 5 + bool rust_helper_is_of_node(const struct fwnode_handle *fwnode) 6 + { 7 + return is_of_node(fwnode); 8 + }
-10
rust/helpers/pci.c
··· 2 2 3 3 #include <linux/pci.h> 4 4 5 - void rust_helper_pci_set_drvdata(struct pci_dev *pdev, void *data) 6 - { 7 - pci_set_drvdata(pdev, data); 8 - } 9 - 10 - void *rust_helper_pci_get_drvdata(struct pci_dev *pdev) 11 - { 12 - return pci_get_drvdata(pdev); 13 - } 14 - 15 5 resource_size_t rust_helper_pci_resource_len(struct pci_dev *pdev, int bar) 16 6 { 17 7 return pci_resource_len(pdev, bar);
-10
rust/helpers/platform.c
··· 2 2 3 3 #include <linux/platform_device.h> 4 4 5 - void *rust_helper_platform_get_drvdata(const struct platform_device *pdev) 6 - { 7 - return platform_get_drvdata(pdev); 8 - } 9 - 10 - void rust_helper_platform_set_drvdata(struct platform_device *pdev, void *data) 11 - { 12 - platform_set_drvdata(pdev, data); 13 - } 14 - 15 5 bool rust_helper_dev_is_platform(const struct device *dev) 16 6 { 17 7 return dev_is_platform(dev);
+8
rust/helpers/property.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/property.h> 4 + 5 + void rust_helper_fwnode_handle_put(struct fwnode_handle *fwnode) 6 + { 7 + fwnode_handle_put(fwnode); 8 + }
+70
rust/kernel/acpi.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Advanced Configuration and Power Interface abstractions. 4 + 5 + use crate::{ 6 + bindings, 7 + device_id::{RawDeviceId, RawDeviceIdIndex}, 8 + prelude::*, 9 + }; 10 + 11 + /// IdTable type for ACPI drivers. 12 + pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; 13 + 14 + /// An ACPI device id. 15 + #[repr(transparent)] 16 + #[derive(Clone, Copy)] 17 + pub struct DeviceId(bindings::acpi_device_id); 18 + 19 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `acpi_device_id` and does not add 20 + // additional invariants, so it's safe to transmute to `RawType`. 21 + unsafe impl RawDeviceId for DeviceId { 22 + type RawType = bindings::acpi_device_id; 23 + } 24 + 25 + // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 26 + unsafe impl RawDeviceIdIndex for DeviceId { 27 + const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::acpi_device_id, driver_data); 28 + 29 + fn index(&self) -> usize { 30 + self.0.driver_data 31 + } 32 + } 33 + 34 + impl DeviceId { 35 + const ACPI_ID_LEN: usize = 16; 36 + 37 + /// Create a new device id from an ACPI 'id' string. 38 + #[inline(always)] 39 + pub const fn new(id: &'static CStr) -> Self { 40 + build_assert!( 41 + id.len_with_nul() <= Self::ACPI_ID_LEN, 42 + "ID exceeds 16 bytes" 43 + ); 44 + let src = id.as_bytes_with_nul(); 45 + // Replace with `bindings::acpi_device_id::default()` once stabilized for `const`. 46 + // SAFETY: FFI type is valid to be zero-initialized. 47 + let mut acpi: bindings::acpi_device_id = unsafe { core::mem::zeroed() }; 48 + let mut i = 0; 49 + while i < src.len() { 50 + acpi.id[i] = src[i]; 51 + i += 1; 52 + } 53 + 54 + Self(acpi) 55 + } 56 + } 57 + 58 + /// Create an ACPI `IdTable` with an "alias" for modpost. 59 + #[macro_export] 60 + macro_rules! acpi_device_table { 61 + ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { 62 + const $table_name: $crate::device_id::IdArray< 63 + $crate::acpi::DeviceId, 64 + $id_info_type, 65 + { $table_data.len() }, 66 + > = $crate::device_id::IdArray::new($table_data); 67 + 68 + $crate::module_device_table!("acpi", $module_table_name, $table_name); 69 + }; 70 + }
+22 -27
rust/kernel/auxiliary.rs
··· 6 6 7 7 use crate::{ 8 8 bindings, container_of, device, 9 - device_id::RawDeviceId, 9 + device_id::{RawDeviceId, RawDeviceIdIndex}, 10 10 driver, 11 - error::{to_result, Result}, 11 + error::{from_result, to_result, Result}, 12 12 prelude::*, 13 - str::CStr, 14 - types::{ForeignOwnable, Opaque}, 13 + types::Opaque, 15 14 ThisModule, 16 15 }; 17 16 use core::{ ··· 60 61 // `struct auxiliary_device`. 61 62 // 62 63 // INVARIANT: `adev` is valid for the duration of `probe_callback()`. 63 - let adev = unsafe { &*adev.cast::<Device<device::Core>>() }; 64 + let adev = unsafe { &*adev.cast::<Device<device::CoreInternal>>() }; 64 65 65 66 // SAFETY: `DeviceId` is a `#[repr(transparent)`] wrapper of `struct auxiliary_device_id` 66 67 // and does not add additional invariants, so it's safe to transmute. 67 68 let id = unsafe { &*id.cast::<DeviceId>() }; 68 69 let info = T::ID_TABLE.info(id.index()); 69 70 70 - match T::probe(adev, info) { 71 - Ok(data) => { 72 - // Let the `struct auxiliary_device` own a reference of the driver's private data. 73 - // SAFETY: By the type invariant `adev.as_raw` returns a valid pointer to a 74 - // `struct auxiliary_device`. 75 - unsafe { 76 - bindings::auxiliary_set_drvdata(adev.as_raw(), data.into_foreign().cast()) 77 - }; 78 - } 79 - Err(err) => return Error::to_errno(err), 80 - } 71 + from_result(|| { 72 + let data = T::probe(adev, info)?; 81 73 82 - 0 74 + adev.as_ref().set_drvdata(data); 75 + Ok(0) 76 + }) 83 77 } 84 78 85 79 extern "C" fn remove_callback(adev: *mut bindings::auxiliary_device) { 86 - // SAFETY: The auxiliary bus only ever calls the remove callback with a valid pointer to a 80 + // SAFETY: The auxiliary bus only ever calls the probe callback with a valid pointer to a 87 81 // `struct auxiliary_device`. 88 - let ptr = unsafe { bindings::auxiliary_get_drvdata(adev) }; 82 + // 83 + // INVARIANT: `adev` is valid for the duration of `probe_callback()`. 84 + let adev = unsafe { &*adev.cast::<Device<device::CoreInternal>>() }; 89 85 90 86 // SAFETY: `remove_callback` is only ever called after a successful call to 91 - // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized 92 - // `KBox<T>` pointer created through `KBox::into_foreign`. 93 - drop(unsafe { KBox::<T>::from_foreign(ptr.cast()) }); 87 + // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 88 + // and stored a `Pin<KBox<T>>`. 89 + drop(unsafe { adev.as_ref().drvdata_obtain::<Pin<KBox<T>>>() }); 94 90 } 95 91 } 96 92 ··· 134 140 } 135 141 } 136 142 137 - // SAFETY: 138 - // * `DeviceId` is a `#[repr(transparent)`] wrapper of `auxiliary_device_id` and does not add 139 - // additional invariants, so it's safe to transmute to `RawType`. 140 - // * `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 143 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `auxiliary_device_id` and does not add 144 + // additional invariants, so it's safe to transmute to `RawType`. 141 145 unsafe impl RawDeviceId for DeviceId { 142 146 type RawType = bindings::auxiliary_device_id; 147 + } 143 148 149 + // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 150 + unsafe impl RawDeviceIdIndex for DeviceId { 144 151 const DRIVER_DATA_OFFSET: usize = 145 152 core::mem::offset_of!(bindings::auxiliary_device_id, driver_data); 146 153 ··· 271 276 let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) }; 272 277 273 278 // SAFETY: `dev` points to a valid `struct device`. 274 - unsafe { device::Device::as_ref(dev) } 279 + unsafe { device::Device::from_raw(dev) } 275 280 } 276 281 } 277 282
+7 -5
rust/kernel/block/mq/tag_set.rs
··· 9 9 use crate::{ 10 10 bindings, 11 11 block::mq::{operations::OperationsVTable, request::RequestDataWrapper, Operations}, 12 - error, 12 + error::{self, Result}, 13 13 prelude::try_pin_init, 14 14 types::Opaque, 15 15 }; ··· 41 41 // SAFETY: `blk_mq_tag_set` only contains integers and pointers, which 42 42 // all are allowed to be 0. 43 43 let tag_set: bindings::blk_mq_tag_set = unsafe { core::mem::zeroed() }; 44 - let tag_set = core::mem::size_of::<RequestDataWrapper>() 44 + let tag_set: Result<_> = core::mem::size_of::<RequestDataWrapper>() 45 45 .try_into() 46 46 .map(|cmd_size| { 47 47 bindings::blk_mq_tag_set { ··· 56 56 nr_maps: num_maps, 57 57 ..tag_set 58 58 } 59 - }); 59 + }) 60 + .map(Opaque::new) 61 + .map_err(|e| e.into()); 60 62 61 63 try_pin_init!(TagSet { 62 - inner <- PinInit::<_, error::Error>::pin_chain(Opaque::new(tag_set?), |tag_set| { 64 + inner <- tag_set.pin_chain(|tag_set| { 63 65 // SAFETY: we do not move out of `tag_set`. 64 - let tag_set = unsafe { Pin::get_unchecked_mut(tag_set) }; 66 + let tag_set: &mut Opaque<_> = unsafe { Pin::get_unchecked_mut(tag_set) }; 65 67 // SAFETY: `tag_set` is a reference to an initialized `blk_mq_tag_set`. 66 68 error::to_result( unsafe { bindings::blk_mq_alloc_tag_set(tag_set.get())}) 67 69 }),
+1 -1
rust/kernel/cpu.rs
··· 147 147 148 148 // SAFETY: The pointer returned by `get_cpu_device()`, if not `NULL`, is a valid pointer to 149 149 // a `struct device` and is never freed by the C code. 150 - Ok(unsafe { Device::as_ref(ptr) }) 150 + Ok(unsafe { Device::from_raw(ptr) }) 151 151 }
+7 -4
rust/kernel/cpufreq.rs
··· 13 13 cpu::CpuId, 14 14 cpumask, 15 15 device::{Bound, Device}, 16 - devres::Devres, 16 + devres, 17 17 error::{code::*, from_err_ptr, from_result, to_result, Result, VTABLE_DEFAULT_ERROR}, 18 18 ffi::{c_char, c_ulong}, 19 19 prelude::*, ··· 1046 1046 1047 1047 /// Same as [`Registration::new`], but does not return a [`Registration`] instance. 1048 1048 /// 1049 - /// Instead the [`Registration`] is owned by [`Devres`] and will be revoked / dropped, once the 1049 + /// Instead the [`Registration`] is owned by [`devres::register`] and will be dropped, once the 1050 1050 /// device is detached. 1051 - pub fn new_foreign_owned(dev: &Device<Bound>) -> Result { 1052 - Devres::new_foreign_owned(dev, Self::new()?, GFP_KERNEL) 1051 + pub fn new_foreign_owned(dev: &Device<Bound>) -> Result 1052 + where 1053 + T: 'static, 1054 + { 1055 + devres::register(dev, Self::new()?, GFP_KERNEL) 1053 1056 } 1054 1057 } 1055 1058
+99 -9
rust/kernel/device.rs
··· 6 6 7 7 use crate::{ 8 8 bindings, 9 - str::CStr, 10 - types::{ARef, Opaque}, 9 + types::{ARef, ForeignOwnable, Opaque}, 11 10 }; 12 11 use core::{fmt, marker::PhantomData, ptr}; 13 12 14 13 #[cfg(CONFIG_PRINTK)] 15 14 use crate::c_str; 15 + 16 + pub mod property; 16 17 17 18 /// A reference-counted device. 18 19 /// ··· 58 57 /// While not officially documented, this should be the case for any `struct device`. 59 58 pub unsafe fn get_device(ptr: *mut bindings::device) -> ARef<Self> { 60 59 // SAFETY: By the safety requirements ptr is valid 61 - unsafe { Self::as_ref(ptr) }.into() 60 + unsafe { Self::from_raw(ptr) }.into() 61 + } 62 + 63 + /// Convert a [`&Device`](Device) into a [`&Device<Bound>`](Device<Bound>). 64 + /// 65 + /// # Safety 66 + /// 67 + /// The caller is responsible to ensure that the returned [`&Device<Bound>`](Device<Bound>) 68 + /// only lives as long as it can be guaranteed that the [`Device`] is actually bound. 69 + pub unsafe fn as_bound(&self) -> &Device<Bound> { 70 + let ptr = core::ptr::from_ref(self); 71 + 72 + // CAST: By the safety requirements the caller is responsible to guarantee that the 73 + // returned reference only lives as long as the device is actually bound. 74 + let ptr = ptr.cast(); 75 + 76 + // SAFETY: 77 + // - `ptr` comes from `from_ref(self)` above, hence it's guaranteed to be valid. 78 + // - Any valid `Device` pointer is also a valid pointer for `Device<Bound>`. 79 + unsafe { &*ptr } 80 + } 81 + } 82 + 83 + impl Device<CoreInternal> { 84 + /// Store a pointer to the bound driver's private data. 85 + pub fn set_drvdata(&self, data: impl ForeignOwnable) { 86 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 87 + unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) } 88 + } 89 + 90 + /// Take ownership of the private data stored in this [`Device`]. 91 + /// 92 + /// # Safety 93 + /// 94 + /// - Must only be called once after a preceding call to [`Device::set_drvdata`]. 95 + /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 96 + /// [`Device::set_drvdata`]. 97 + pub unsafe fn drvdata_obtain<T: ForeignOwnable>(&self) -> T { 98 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 99 + let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) }; 100 + 101 + // SAFETY: 102 + // - By the safety requirements of this function, `ptr` comes from a previous call to 103 + // `into_foreign()`. 104 + // - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()` 105 + // in `into_foreign()`. 106 + unsafe { T::from_foreign(ptr.cast()) } 107 + } 108 + 109 + /// Borrow the driver's private data bound to this [`Device`]. 110 + /// 111 + /// # Safety 112 + /// 113 + /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before 114 + /// [`Device::drvdata_obtain`]. 115 + /// - The type `T` must match the type of the `ForeignOwnable` previously stored by 116 + /// [`Device::set_drvdata`]. 117 + pub unsafe fn drvdata_borrow<T: ForeignOwnable>(&self) -> T::Borrowed<'_> { 118 + // SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`. 119 + let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) }; 120 + 121 + // SAFETY: 122 + // - By the safety requirements of this function, `ptr` comes from a previous call to 123 + // `into_foreign()`. 124 + // - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()` 125 + // in `into_foreign()`. 126 + unsafe { T::borrow(ptr.cast()) } 62 127 } 63 128 } 64 129 ··· 149 82 // - Since `parent` is not NULL, it must be a valid pointer to a `struct device`. 150 83 // - `parent` is valid for the lifetime of `self`, since a `struct device` holds a 151 84 // reference count of its parent. 152 - Some(unsafe { Self::as_ref(parent) }) 85 + Some(unsafe { Self::from_raw(parent) }) 153 86 } 154 87 } 155 88 ··· 161 94 /// i.e. it must be ensured that the reference count of the C `struct device` `ptr` points to 162 95 /// can't drop to zero, for the duration of this function call and the entire duration when the 163 96 /// returned reference exists. 164 - pub unsafe fn as_ref<'a>(ptr: *mut bindings::device) -> &'a Self { 97 + pub unsafe fn from_raw<'a>(ptr: *mut bindings::device) -> &'a Self { 165 98 // SAFETY: Guaranteed by the safety requirements of the function. 166 99 unsafe { &*ptr.cast() } 167 100 } ··· 270 203 }; 271 204 } 272 205 273 - /// Checks if property is present or not. 274 - pub fn property_present(&self, name: &CStr) -> bool { 275 - // SAFETY: By the invariant of `CStr`, `name` is null-terminated. 276 - unsafe { bindings::device_property_present(self.as_raw().cast_const(), name.as_char_ptr()) } 206 + /// Obtain the [`FwNode`](property::FwNode) corresponding to this [`Device`]. 207 + pub fn fwnode(&self) -> Option<&property::FwNode> { 208 + // SAFETY: `self` is valid. 209 + let fwnode_handle = unsafe { bindings::__dev_fwnode(self.as_raw()) }; 210 + if fwnode_handle.is_null() { 211 + return None; 212 + } 213 + // SAFETY: `fwnode_handle` is valid. Its lifetime is tied to `&self`. We 214 + // return a reference instead of an `ARef<FwNode>` because `dev_fwnode()` 215 + // doesn't increment the refcount. It is safe to cast from a 216 + // `struct fwnode_handle*` to a `*const FwNode` because `FwNode` is 217 + // defined as a `#[repr(transparent)]` wrapper around `fwnode_handle`. 218 + Some(unsafe { &*fwnode_handle.cast() }) 277 219 } 278 220 } 279 221 ··· 327 251 /// any of the bus callbacks, such as `probe()`. 328 252 pub struct Core; 329 253 254 + /// Semantically the same as [`Core`] but reserved for internal usage of the corresponding bus 255 + /// abstraction. 256 + pub struct CoreInternal; 257 + 330 258 /// The [`Bound`] context is the context of a bus specific device reference when it is guaranteed to 331 259 /// be bound for the duration of its lifetime. 332 260 pub struct Bound; ··· 340 260 341 261 impl Sealed for super::Bound {} 342 262 impl Sealed for super::Core {} 263 + impl Sealed for super::CoreInternal {} 343 264 impl Sealed for super::Normal {} 344 265 } 345 266 346 267 impl DeviceContext for Bound {} 347 268 impl DeviceContext for Core {} 269 + impl DeviceContext for CoreInternal {} 348 270 impl DeviceContext for Normal {} 349 271 350 272 /// # Safety ··· 388 306 // `__impl_device_context_deref!`. 389 307 ::kernel::__impl_device_context_deref!(unsafe { 390 308 $device, 309 + $crate::device::CoreInternal => $crate::device::Core 310 + }); 311 + 312 + // SAFETY: This macro has the exact same safety requirement as 313 + // `__impl_device_context_deref!`. 314 + ::kernel::__impl_device_context_deref!(unsafe { 315 + $device, 391 316 $crate::device::Core => $crate::device::Bound 392 317 }); 393 318 ··· 424 335 #[macro_export] 425 336 macro_rules! impl_device_context_into_aref { 426 337 ($device:tt) => { 338 + ::kernel::__impl_device_context_into_aref!($crate::device::CoreInternal, $device); 427 339 ::kernel::__impl_device_context_into_aref!($crate::device::Core, $device); 428 340 ::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device); 429 341 };
+631
rust/kernel/device/property.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Unified device property interface. 4 + //! 5 + //! C header: [`include/linux/property.h`](srctree/include/linux/property.h) 6 + 7 + use core::{mem::MaybeUninit, ptr}; 8 + 9 + use super::private::Sealed; 10 + use crate::{ 11 + alloc::KVec, 12 + bindings, 13 + error::{to_result, Result}, 14 + prelude::*, 15 + str::{CStr, CString}, 16 + types::{ARef, Opaque}, 17 + }; 18 + 19 + /// A reference-counted fwnode_handle. 20 + /// 21 + /// This structure represents the Rust abstraction for a 22 + /// C `struct fwnode_handle`. This implementation abstracts the usage of an 23 + /// already existing C `struct fwnode_handle` within Rust code that we get 24 + /// passed from the C side. 25 + /// 26 + /// # Invariants 27 + /// 28 + /// A `FwNode` instance represents a valid `struct fwnode_handle` created by the 29 + /// C portion of the kernel. 30 + /// 31 + /// Instances of this type are always reference-counted, that is, a call to 32 + /// `fwnode_handle_get` ensures that the allocation remains valid at least until 33 + /// the matching call to `fwnode_handle_put`. 34 + #[repr(transparent)] 35 + pub struct FwNode(Opaque<bindings::fwnode_handle>); 36 + 37 + impl FwNode { 38 + /// # Safety 39 + /// 40 + /// Callers must ensure that: 41 + /// - The reference count was incremented at least once. 42 + /// - They relinquish that increment. That is, if there is only one 43 + /// increment, callers must not use the underlying object anymore -- it is 44 + /// only safe to do so via the newly created `ARef<FwNode>`. 45 + unsafe fn from_raw(raw: *mut bindings::fwnode_handle) -> ARef<Self> { 46 + // SAFETY: As per the safety requirements of this function: 47 + // - `NonNull::new_unchecked`: 48 + // - `raw` is not null. 49 + // - `ARef::from_raw`: 50 + // - `raw` has an incremented refcount. 51 + // - that increment is relinquished, i.e. it won't be decremented 52 + // elsewhere. 53 + // CAST: It is safe to cast from a `*mut fwnode_handle` to 54 + // `*mut FwNode`, because `FwNode` is defined as a 55 + // `#[repr(transparent)]` wrapper around `fwnode_handle`. 56 + unsafe { ARef::from_raw(ptr::NonNull::new_unchecked(raw.cast())) } 57 + } 58 + 59 + /// Obtain the raw `struct fwnode_handle *`. 60 + pub(crate) fn as_raw(&self) -> *mut bindings::fwnode_handle { 61 + self.0.get() 62 + } 63 + 64 + /// Returns `true` if `&self` is an OF node, `false` otherwise. 65 + pub fn is_of_node(&self) -> bool { 66 + // SAFETY: The type invariant of `Self` guarantees that `self.as_raw() is a pointer to a 67 + // valid `struct fwnode_handle`. 68 + unsafe { bindings::is_of_node(self.as_raw()) } 69 + } 70 + 71 + /// Returns an object that implements [`Display`](core::fmt::Display) for 72 + /// printing the name of a node. 73 + /// 74 + /// This is an alternative to the default `Display` implementation, which 75 + /// prints the full path. 76 + pub fn display_name(&self) -> impl core::fmt::Display + '_ { 77 + struct FwNodeDisplayName<'a>(&'a FwNode); 78 + 79 + impl core::fmt::Display for FwNodeDisplayName<'_> { 80 + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 81 + // SAFETY: `self` is valid by its type invariant. 82 + let name = unsafe { bindings::fwnode_get_name(self.0.as_raw()) }; 83 + if name.is_null() { 84 + return Ok(()); 85 + } 86 + // SAFETY: 87 + // - `fwnode_get_name` returns null or a valid C string. 88 + // - `name` was checked to be non-null. 89 + let name = unsafe { CStr::from_char_ptr(name) }; 90 + write!(f, "{name}") 91 + } 92 + } 93 + 94 + FwNodeDisplayName(self) 95 + } 96 + 97 + /// Checks if property is present or not. 98 + pub fn property_present(&self, name: &CStr) -> bool { 99 + // SAFETY: By the invariant of `CStr`, `name` is null-terminated. 100 + unsafe { bindings::fwnode_property_present(self.as_raw().cast_const(), name.as_char_ptr()) } 101 + } 102 + 103 + /// Returns firmware property `name` boolean value. 104 + pub fn property_read_bool(&self, name: &CStr) -> bool { 105 + // SAFETY: 106 + // - `name` is non-null and null-terminated. 107 + // - `self.as_raw()` is valid because `self` is valid. 108 + unsafe { bindings::fwnode_property_read_bool(self.as_raw(), name.as_char_ptr()) } 109 + } 110 + 111 + /// Returns the index of matching string `match_str` for firmware string 112 + /// property `name`. 113 + pub fn property_match_string(&self, name: &CStr, match_str: &CStr) -> Result<usize> { 114 + // SAFETY: 115 + // - `name` and `match_str` are non-null and null-terminated. 116 + // - `self.as_raw` is valid because `self` is valid. 117 + let ret = unsafe { 118 + bindings::fwnode_property_match_string( 119 + self.as_raw(), 120 + name.as_char_ptr(), 121 + match_str.as_char_ptr(), 122 + ) 123 + }; 124 + to_result(ret)?; 125 + Ok(ret as usize) 126 + } 127 + 128 + /// Returns firmware property `name` integer array values in a [`KVec`]. 129 + pub fn property_read_array_vec<'fwnode, 'name, T: PropertyInt>( 130 + &'fwnode self, 131 + name: &'name CStr, 132 + len: usize, 133 + ) -> Result<PropertyGuard<'fwnode, 'name, KVec<T>>> { 134 + let mut val: KVec<T> = KVec::with_capacity(len, GFP_KERNEL)?; 135 + 136 + let res = T::read_array_from_fwnode_property(self, name, val.spare_capacity_mut()); 137 + let res = match res { 138 + Ok(_) => { 139 + // SAFETY: 140 + // - `len` is equal to `val.capacity - val.len`, because 141 + // `val.capacity` is `len` and `val.len` is zero. 142 + // - All elements within the interval [`0`, `len`) were initialized 143 + // by `read_array_from_fwnode_property`. 144 + unsafe { val.inc_len(len) } 145 + Ok(val) 146 + } 147 + Err(e) => Err(e), 148 + }; 149 + Ok(PropertyGuard { 150 + inner: res, 151 + fwnode: self, 152 + name, 153 + }) 154 + } 155 + 156 + /// Returns integer array length for firmware property `name`. 157 + pub fn property_count_elem<T: PropertyInt>(&self, name: &CStr) -> Result<usize> { 158 + T::read_array_len_from_fwnode_property(self, name) 159 + } 160 + 161 + /// Returns the value of firmware property `name`. 162 + /// 163 + /// This method is generic over the type of value to read. The types that 164 + /// can be read are strings, integers and arrays of integers. 165 + /// 166 + /// Reading a [`KVec`] of integers is done with the separate 167 + /// method [`Self::property_read_array_vec`], because it takes an 168 + /// additional `len` argument. 169 + /// 170 + /// Reading a boolean is done with the separate method 171 + /// [`Self::property_read_bool`], because this operation is infallible. 172 + /// 173 + /// For more precise documentation about what types can be read, see 174 + /// the [implementors of Property][Property#implementors] and [its 175 + /// implementations on foreign types][Property#foreign-impls]. 176 + /// 177 + /// # Examples 178 + /// 179 + /// ``` 180 + /// # use kernel::{c_str, device::{Device, property::FwNode}, str::CString}; 181 + /// fn examples(dev: &Device) -> Result { 182 + /// let fwnode = dev.fwnode().ok_or(ENOENT)?; 183 + /// let b: u32 = fwnode.property_read(c_str!("some-number")).required_by(dev)?; 184 + /// if let Some(s) = fwnode.property_read::<CString>(c_str!("some-str")).optional() { 185 + /// // ... 186 + /// } 187 + /// Ok(()) 188 + /// } 189 + /// ``` 190 + pub fn property_read<'fwnode, 'name, T: Property>( 191 + &'fwnode self, 192 + name: &'name CStr, 193 + ) -> PropertyGuard<'fwnode, 'name, T> { 194 + PropertyGuard { 195 + inner: T::read_from_fwnode_property(self, name), 196 + fwnode: self, 197 + name, 198 + } 199 + } 200 + 201 + /// Returns first matching named child node handle. 202 + pub fn get_child_by_name(&self, name: &CStr) -> Option<ARef<Self>> { 203 + // SAFETY: `self` and `name` are valid by their type invariants. 204 + let child = 205 + unsafe { bindings::fwnode_get_named_child_node(self.as_raw(), name.as_char_ptr()) }; 206 + if child.is_null() { 207 + return None; 208 + } 209 + // SAFETY: 210 + // - `fwnode_get_named_child_node` returns a pointer with its refcount 211 + // incremented. 212 + // - That increment is relinquished, i.e. the underlying object is not 213 + // used anymore except via the newly created `ARef`. 214 + Some(unsafe { Self::from_raw(child) }) 215 + } 216 + 217 + /// Returns an iterator over a node's children. 218 + pub fn children<'a>(&'a self) -> impl Iterator<Item = ARef<FwNode>> + 'a { 219 + let mut prev: Option<ARef<FwNode>> = None; 220 + 221 + core::iter::from_fn(move || { 222 + let prev_ptr = match prev.take() { 223 + None => ptr::null_mut(), 224 + Some(prev) => { 225 + // We will pass `prev` to `fwnode_get_next_child_node`, 226 + // which decrements its refcount, so we use 227 + // `ARef::into_raw` to avoid decrementing the refcount 228 + // twice. 229 + let prev = ARef::into_raw(prev); 230 + prev.as_ptr().cast() 231 + } 232 + }; 233 + // SAFETY: 234 + // - `self.as_raw()` is valid by its type invariant. 235 + // - `prev_ptr` may be null, which is allowed and corresponds to 236 + // getting the first child. Otherwise, `prev_ptr` is valid, as it 237 + // is the stored return value from the previous invocation. 238 + // - `prev_ptr` has its refount incremented. 239 + // - The increment of `prev_ptr` is relinquished, i.e. the 240 + // underlying object won't be used anymore. 241 + let next = unsafe { bindings::fwnode_get_next_child_node(self.as_raw(), prev_ptr) }; 242 + if next.is_null() { 243 + return None; 244 + } 245 + // SAFETY: 246 + // - `next` is valid because `fwnode_get_next_child_node` returns a 247 + // pointer with its refcount incremented. 248 + // - That increment is relinquished, i.e. the underlying object 249 + // won't be used anymore, except via the newly created 250 + // `ARef<Self>`. 251 + let next = unsafe { FwNode::from_raw(next) }; 252 + prev = Some(next.clone()); 253 + Some(next) 254 + }) 255 + } 256 + 257 + /// Finds a reference with arguments. 258 + pub fn property_get_reference_args( 259 + &self, 260 + prop: &CStr, 261 + nargs: NArgs<'_>, 262 + index: u32, 263 + ) -> Result<FwNodeReferenceArgs> { 264 + let mut out_args = FwNodeReferenceArgs::default(); 265 + 266 + let (nargs_prop, nargs) = match nargs { 267 + NArgs::Prop(nargs_prop) => (nargs_prop.as_char_ptr(), 0), 268 + NArgs::N(nargs) => (ptr::null(), nargs), 269 + }; 270 + 271 + // SAFETY: 272 + // - `self.0.get()` is valid. 273 + // - `prop.as_char_ptr()` is valid and zero-terminated. 274 + // - `nargs_prop` is valid and zero-terminated if `nargs` 275 + // is zero, otherwise it is allowed to be a null-pointer. 276 + // - The function upholds the type invariants of `out_args`, 277 + // namely: 278 + // - It may fill the field `fwnode` with a valid pointer, 279 + // in which case its refcount is incremented. 280 + // - It may modify the field `nargs`, in which case it 281 + // initializes at least as many elements in `args`. 282 + let ret = unsafe { 283 + bindings::fwnode_property_get_reference_args( 284 + self.0.get(), 285 + prop.as_char_ptr(), 286 + nargs_prop, 287 + nargs, 288 + index, 289 + &mut out_args.0, 290 + ) 291 + }; 292 + to_result(ret)?; 293 + 294 + Ok(out_args) 295 + } 296 + } 297 + 298 + /// The number of arguments to request [`FwNodeReferenceArgs`]. 299 + pub enum NArgs<'a> { 300 + /// The name of the property of the reference indicating the number of 301 + /// arguments. 302 + Prop(&'a CStr), 303 + /// The known number of arguments. 304 + N(u32), 305 + } 306 + 307 + /// The return value of [`FwNode::property_get_reference_args`]. 308 + /// 309 + /// This structure represents the Rust abstraction for a C 310 + /// `struct fwnode_reference_args` which was initialized by the C side. 311 + /// 312 + /// # Invariants 313 + /// 314 + /// If the field `fwnode` is valid, it owns an increment of its refcount. 315 + /// 316 + /// The field `args` contains at least as many initialized elements as indicated 317 + /// by the field `nargs`. 318 + #[repr(transparent)] 319 + #[derive(Default)] 320 + pub struct FwNodeReferenceArgs(bindings::fwnode_reference_args); 321 + 322 + impl Drop for FwNodeReferenceArgs { 323 + fn drop(&mut self) { 324 + if !self.0.fwnode.is_null() { 325 + // SAFETY: 326 + // - By the type invariants of `FwNodeReferenceArgs`, its field 327 + // `fwnode` owns an increment of its refcount. 328 + // - That increment is relinquished. The underlying object won't be 329 + // used anymore because we are dropping it. 330 + let _ = unsafe { FwNode::from_raw(self.0.fwnode) }; 331 + } 332 + } 333 + } 334 + 335 + impl FwNodeReferenceArgs { 336 + /// Returns the slice of reference arguments. 337 + pub fn as_slice(&self) -> &[u64] { 338 + // SAFETY: As per the safety invariant of `FwNodeReferenceArgs`, `nargs` 339 + // is the minimum number of elements in `args` that is valid. 340 + unsafe { core::slice::from_raw_parts(self.0.args.as_ptr(), self.0.nargs as usize) } 341 + } 342 + 343 + /// Returns the number of reference arguments. 344 + pub fn len(&self) -> usize { 345 + self.0.nargs as usize 346 + } 347 + 348 + /// Returns `true` if there are no reference arguments. 349 + pub fn is_empty(&self) -> bool { 350 + self.0.nargs == 0 351 + } 352 + } 353 + 354 + impl core::fmt::Debug for FwNodeReferenceArgs { 355 + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 356 + write!(f, "{:?}", self.as_slice()) 357 + } 358 + } 359 + 360 + // SAFETY: Instances of `FwNode` are always reference-counted. 361 + unsafe impl crate::types::AlwaysRefCounted for FwNode { 362 + fn inc_ref(&self) { 363 + // SAFETY: The existence of a shared reference guarantees that the 364 + // refcount is non-zero. 365 + unsafe { bindings::fwnode_handle_get(self.as_raw()) }; 366 + } 367 + 368 + unsafe fn dec_ref(obj: ptr::NonNull<Self>) { 369 + // SAFETY: The safety requirements guarantee that the refcount is 370 + // non-zero. 371 + unsafe { bindings::fwnode_handle_put(obj.cast().as_ptr()) } 372 + } 373 + } 374 + 375 + enum Node<'a> { 376 + Borrowed(&'a FwNode), 377 + Owned(ARef<FwNode>), 378 + } 379 + 380 + impl core::fmt::Display for FwNode { 381 + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 382 + // The logic here is the same as the one in lib/vsprintf.c 383 + // (fwnode_full_name_string). 384 + 385 + // SAFETY: `self.as_raw()` is valid by its type invariant. 386 + let num_parents = unsafe { bindings::fwnode_count_parents(self.as_raw()) }; 387 + 388 + for depth in (0..=num_parents).rev() { 389 + let fwnode = if depth == 0 { 390 + Node::Borrowed(self) 391 + } else { 392 + // SAFETY: `self.as_raw()` is valid. 393 + let ptr = unsafe { bindings::fwnode_get_nth_parent(self.as_raw(), depth) }; 394 + // SAFETY: 395 + // - The depth passed to `fwnode_get_nth_parent` is 396 + // within the valid range, so the returned pointer is 397 + // not null. 398 + // - The reference count was incremented by 399 + // `fwnode_get_nth_parent`. 400 + // - That increment is relinquished to 401 + // `FwNode::from_raw`. 402 + Node::Owned(unsafe { FwNode::from_raw(ptr) }) 403 + }; 404 + // Take a reference to the owned or borrowed `FwNode`. 405 + let fwnode: &FwNode = match &fwnode { 406 + Node::Borrowed(f) => f, 407 + Node::Owned(f) => f, 408 + }; 409 + 410 + // SAFETY: `fwnode` is valid by its type invariant. 411 + let prefix = unsafe { bindings::fwnode_get_name_prefix(fwnode.as_raw()) }; 412 + if !prefix.is_null() { 413 + // SAFETY: `fwnode_get_name_prefix` returns null or a 414 + // valid C string. 415 + let prefix = unsafe { CStr::from_char_ptr(prefix) }; 416 + write!(f, "{prefix}")?; 417 + } 418 + write!(f, "{}", fwnode.display_name())?; 419 + } 420 + 421 + Ok(()) 422 + } 423 + } 424 + 425 + /// Implemented for types that can be read as properties. 426 + /// 427 + /// This is implemented for strings, integers and arrays of integers. It's used 428 + /// to make [`FwNode::property_read`] generic over the type of property being 429 + /// read. There are also two dedicated methods to read other types, because they 430 + /// require more specialized function signatures: 431 + /// - [`property_read_bool`](FwNode::property_read_bool) 432 + /// - [`property_read_array_vec`](FwNode::property_read_array_vec) 433 + /// 434 + /// It must be public, because it appears in the signatures of other public 435 + /// functions, but its methods shouldn't be used outside the kernel crate. 436 + pub trait Property: Sized + Sealed { 437 + /// Used to make [`FwNode::property_read`] generic. 438 + fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self>; 439 + } 440 + 441 + impl Sealed for CString {} 442 + 443 + impl Property for CString { 444 + fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> { 445 + let mut str: *mut u8 = ptr::null_mut(); 446 + let pstr: *mut _ = &mut str; 447 + 448 + // SAFETY: 449 + // - `name` is non-null and null-terminated. 450 + // - `fwnode.as_raw` is valid because `fwnode` is valid. 451 + let ret = unsafe { 452 + bindings::fwnode_property_read_string(fwnode.as_raw(), name.as_char_ptr(), pstr.cast()) 453 + }; 454 + to_result(ret)?; 455 + 456 + // SAFETY: 457 + // - `pstr` is a valid pointer to a NUL-terminated C string. 458 + // - It is valid for at least as long as `fwnode`, but it's only used 459 + // within the current function. 460 + // - The memory it points to is not mutated during that time. 461 + let str = unsafe { CStr::from_char_ptr(*pstr) }; 462 + Ok(str.try_into()?) 463 + } 464 + } 465 + 466 + /// Implemented for all integers that can be read as properties. 467 + /// 468 + /// This helper trait is needed on top of the existing [`Property`] 469 + /// trait to associate the integer types of various sizes with their 470 + /// corresponding `fwnode_property_read_*_array` functions. 471 + /// 472 + /// It must be public, because it appears in the signatures of other public 473 + /// functions, but its methods shouldn't be used outside the kernel crate. 474 + pub trait PropertyInt: Copy + Sealed { 475 + /// Reads a property array. 476 + fn read_array_from_fwnode_property<'a>( 477 + fwnode: &FwNode, 478 + name: &CStr, 479 + out: &'a mut [MaybeUninit<Self>], 480 + ) -> Result<&'a mut [Self]>; 481 + 482 + /// Reads the length of a property array. 483 + fn read_array_len_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<usize>; 484 + } 485 + // This macro generates implementations of the traits `Property` and 486 + // `PropertyInt` for integers of various sizes. Its input is a list 487 + // of pairs separated by commas. The first element of the pair is the 488 + // type of the integer, the second one is the name of its corresponding 489 + // `fwnode_property_read_*_array` function. 490 + macro_rules! impl_property_for_int { 491 + ($($int:ty: $f:ident),* $(,)?) => { $( 492 + impl Sealed for $int {} 493 + impl<const N: usize> Sealed for [$int; N] {} 494 + 495 + impl PropertyInt for $int { 496 + fn read_array_from_fwnode_property<'a>( 497 + fwnode: &FwNode, 498 + name: &CStr, 499 + out: &'a mut [MaybeUninit<Self>], 500 + ) -> Result<&'a mut [Self]> { 501 + // SAFETY: 502 + // - `fwnode`, `name` and `out` are all valid by their type 503 + // invariants. 504 + // - `out.len()` is a valid bound for the memory pointed to by 505 + // `out.as_mut_ptr()`. 506 + // CAST: It's ok to cast from `*mut MaybeUninit<$int>` to a 507 + // `*mut $int` because they have the same memory layout. 508 + let ret = unsafe { 509 + bindings::$f( 510 + fwnode.as_raw(), 511 + name.as_char_ptr(), 512 + out.as_mut_ptr().cast(), 513 + out.len(), 514 + ) 515 + }; 516 + to_result(ret)?; 517 + // SAFETY: Transmuting from `&'a mut [MaybeUninit<Self>]` to 518 + // `&'a mut [Self]` is sound, because the previous call to a 519 + // `fwnode_property_read_*_array` function (which didn't fail) 520 + // fully initialized the slice. 521 + Ok(unsafe { core::mem::transmute::<&mut [MaybeUninit<Self>], &mut [Self]>(out) }) 522 + } 523 + 524 + fn read_array_len_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<usize> { 525 + // SAFETY: 526 + // - `fwnode` and `name` are valid by their type invariants. 527 + // - It's ok to pass a null pointer to the 528 + // `fwnode_property_read_*_array` functions if `nval` is zero. 529 + // This will return the length of the array. 530 + let ret = unsafe { 531 + bindings::$f( 532 + fwnode.as_raw(), 533 + name.as_char_ptr(), 534 + ptr::null_mut(), 535 + 0, 536 + ) 537 + }; 538 + to_result(ret)?; 539 + Ok(ret as usize) 540 + } 541 + } 542 + 543 + impl Property for $int { 544 + fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> { 545 + let val: [_; 1] = <[$int; 1]>::read_from_fwnode_property(fwnode, name)?; 546 + Ok(val[0]) 547 + } 548 + } 549 + 550 + impl<const N: usize> Property for [$int; N] { 551 + fn read_from_fwnode_property(fwnode: &FwNode, name: &CStr) -> Result<Self> { 552 + let mut val: [MaybeUninit<$int>; N] = [const { MaybeUninit::uninit() }; N]; 553 + 554 + <$int>::read_array_from_fwnode_property(fwnode, name, &mut val)?; 555 + 556 + // SAFETY: `val` is always initialized when 557 + // `fwnode_property_read_*_array` is successful. 558 + Ok(val.map(|v| unsafe { v.assume_init() })) 559 + } 560 + } 561 + )* }; 562 + } 563 + impl_property_for_int! { 564 + u8: fwnode_property_read_u8_array, 565 + u16: fwnode_property_read_u16_array, 566 + u32: fwnode_property_read_u32_array, 567 + u64: fwnode_property_read_u64_array, 568 + i8: fwnode_property_read_u8_array, 569 + i16: fwnode_property_read_u16_array, 570 + i32: fwnode_property_read_u32_array, 571 + i64: fwnode_property_read_u64_array, 572 + } 573 + 574 + /// A helper for reading device properties. 575 + /// 576 + /// Use [`Self::required_by`] if a missing property is considered a bug and 577 + /// [`Self::optional`] otherwise. 578 + /// 579 + /// For convenience, [`Self::or`] and [`Self::or_default`] are provided. 580 + pub struct PropertyGuard<'fwnode, 'name, T> { 581 + /// The result of reading the property. 582 + inner: Result<T>, 583 + /// The fwnode of the property, used for logging in the "required" case. 584 + fwnode: &'fwnode FwNode, 585 + /// The name of the property, used for logging in the "required" case. 586 + name: &'name CStr, 587 + } 588 + 589 + impl<T> PropertyGuard<'_, '_, T> { 590 + /// Access the property, indicating it is required. 591 + /// 592 + /// If the property is not present, the error is automatically logged. If a 593 + /// missing property is not an error, use [`Self::optional`] instead. The 594 + /// device is required to associate the log with it. 595 + pub fn required_by(self, dev: &super::Device) -> Result<T> { 596 + if self.inner.is_err() { 597 + dev_err!( 598 + dev, 599 + "{}: property '{}' is missing\n", 600 + self.fwnode, 601 + self.name 602 + ); 603 + } 604 + self.inner 605 + } 606 + 607 + /// Access the property, indicating it is optional. 608 + /// 609 + /// In contrast to [`Self::required_by`], no error message is logged if 610 + /// the property is not present. 611 + pub fn optional(self) -> Option<T> { 612 + self.inner.ok() 613 + } 614 + 615 + /// Access the property or the specified default value. 616 + /// 617 + /// Do not pass a sentinel value as default to detect a missing property. 618 + /// Use [`Self::required_by`] or [`Self::optional`] instead. 619 + pub fn or(self, default: T) -> T { 620 + self.inner.unwrap_or(default) 621 + } 622 + } 623 + 624 + impl<T: Default> PropertyGuard<'_, '_, T> { 625 + /// Access the property or a default value. 626 + /// 627 + /// Use [`Self::or`] to specify a custom default value. 628 + pub fn or_default(self) -> T { 629 + self.inner.unwrap_or_default() 630 + } 631 + }
+66 -25
rust/kernel/device_id.rs
··· 14 14 /// 15 15 /// # Safety 16 16 /// 17 - /// Implementers must ensure that: 18 - /// - `Self` is layout-compatible with [`RawDeviceId::RawType`]; i.e. it's safe to transmute to 19 - /// `RawDeviceId`. 17 + /// Implementers must ensure that `Self` is layout-compatible with [`RawDeviceId::RawType`]; 18 + /// i.e. it's safe to transmute to `RawDeviceId`. 20 19 /// 21 - /// This requirement is needed so `IdArray::new` can convert `Self` to `RawType` when building 22 - /// the ID table. 20 + /// This requirement is needed so `IdArray::new` can convert `Self` to `RawType` when building 21 + /// the ID table. 23 22 /// 24 - /// Ideally, this should be achieved using a const function that does conversion instead of 25 - /// transmute; however, const trait functions relies on `const_trait_impl` unstable feature, 26 - /// which is broken/gone in Rust 1.73. 27 - /// 28 - /// - `DRIVER_DATA_OFFSET` is the offset of context/data field of the device ID (usually named 29 - /// `driver_data`) of the device ID, the field is suitable sized to write a `usize` value. 30 - /// 31 - /// Similar to the previous requirement, the data should ideally be added during `Self` to 32 - /// `RawType` conversion, but there's currently no way to do it when using traits in const. 23 + /// Ideally, this should be achieved using a const function that does conversion instead of 24 + /// transmute; however, const trait functions relies on `const_trait_impl` unstable feature, 25 + /// which is broken/gone in Rust 1.73. 33 26 pub unsafe trait RawDeviceId { 34 27 /// The raw type that holds the device id. 35 28 /// 36 29 /// Id tables created from [`Self`] are going to hold this type in its zero-terminated array. 37 30 type RawType: Copy; 31 + } 38 32 39 - /// The offset to the context/data field. 33 + /// Extension trait for [`RawDeviceId`] for devices that embed an index or context value. 34 + /// 35 + /// This is typically used when the device ID struct includes a field like `driver_data` 36 + /// that is used to store a pointer-sized value (e.g., an index or context pointer). 37 + /// 38 + /// # Safety 39 + /// 40 + /// Implementers must ensure that `DRIVER_DATA_OFFSET` is the correct offset (in bytes) to 41 + /// the context/data field (e.g., the `driver_data` field) within the raw device ID structure. 42 + /// This field must be correctly sized to hold a `usize`. 43 + /// 44 + /// Ideally, the data should be added during `Self` to `RawType` conversion, 45 + /// but there's currently no way to do it when using traits in const. 46 + pub unsafe trait RawDeviceIdIndex: RawDeviceId { 47 + /// The offset (in bytes) to the context/data field in the raw device ID. 40 48 const DRIVER_DATA_OFFSET: usize; 41 49 42 - /// The index stored at `DRIVER_DATA_OFFSET` of the implementor of the [`RawDeviceId`] trait. 50 + /// The index stored at `DRIVER_DATA_OFFSET` of the implementor of the [`RawDeviceIdIndex`] 51 + /// trait. 43 52 fn index(&self) -> usize; 44 53 } 45 54 ··· 77 68 /// Creates a new instance of the array. 78 69 /// 79 70 /// The contents are derived from the given identifiers and context information. 80 - pub const fn new(ids: [(T, U); N]) -> Self { 71 + /// 72 + /// # Safety 73 + /// 74 + /// `data_offset` as `None` is always safe. 75 + /// If `data_offset` is `Some(data_offset)`, then: 76 + /// - `data_offset` must be the correct offset (in bytes) to the context/data field 77 + /// (e.g., the `driver_data` field) within the raw device ID structure. 78 + /// - The field at `data_offset` must be correctly sized to hold a `usize`. 79 + const unsafe fn build(ids: [(T, U); N], data_offset: Option<usize>) -> Self { 81 80 let mut raw_ids = [const { MaybeUninit::<T::RawType>::uninit() }; N]; 82 81 let mut infos = [const { MaybeUninit::uninit() }; N]; 83 82 ··· 94 77 // SAFETY: by the safety requirement of `RawDeviceId`, we're guaranteed that `T` is 95 78 // layout-wise compatible with `RawType`. 96 79 raw_ids[i] = unsafe { core::mem::transmute_copy(&ids[i].0) }; 97 - // SAFETY: by the safety requirement of `RawDeviceId`, this would be effectively 98 - // `raw_ids[i].driver_data = i;`. 99 - unsafe { 100 - raw_ids[i] 101 - .as_mut_ptr() 102 - .byte_offset(T::DRIVER_DATA_OFFSET as _) 103 - .cast::<usize>() 104 - .write(i); 80 + if let Some(data_offset) = data_offset { 81 + // SAFETY: by the safety requirement of this function, this would be effectively 82 + // `raw_ids[i].driver_data = i;`. 83 + unsafe { 84 + raw_ids[i] 85 + .as_mut_ptr() 86 + .byte_offset(data_offset as _) 87 + .cast::<usize>() 88 + .write(i); 89 + } 105 90 } 106 91 107 92 // SAFETY: this is effectively a move: `infos[i] = ids[i].1`. We make a copy here but ··· 128 109 } 129 110 } 130 111 112 + /// Creates a new instance of the array without writing index values. 113 + /// 114 + /// The contents are derived from the given identifiers and context information. 115 + /// If the device implements [`RawDeviceIdIndex`], consider using [`IdArray::new`] instead. 116 + pub const fn new_without_index(ids: [(T, U); N]) -> Self { 117 + // SAFETY: Calling `Self::build` with `offset = None` is always safe, 118 + // because no raw memory writes are performed in this case. 119 + unsafe { Self::build(ids, None) } 120 + } 121 + 131 122 /// Reference to the contained [`RawIdArray`]. 132 123 pub const fn raw_ids(&self) -> &RawIdArray<T, N> { 133 124 &self.raw_ids 125 + } 126 + } 127 + 128 + impl<T: RawDeviceId + RawDeviceIdIndex, U, const N: usize> IdArray<T, U, N> { 129 + /// Creates a new instance of the array. 130 + /// 131 + /// The contents are derived from the given identifiers and context information. 132 + pub const fn new(ids: [(T, U); N]) -> Self { 133 + // SAFETY: by the safety requirement of `RawDeviceIdIndex`, 134 + // `T::DRIVER_DATA_OFFSET` is guaranteed to be the correct offset (in bytes) to 135 + // a field within `T::RawType`. 136 + unsafe { Self::build(ids, Some(T::DRIVER_DATA_OFFSET)) } 134 137 } 135 138 } 136 139
+193 -96
rust/kernel/devres.rs
··· 9 9 alloc::Flags, 10 10 bindings, 11 11 device::{Bound, Device}, 12 - error::{Error, Result}, 12 + error::{to_result, Error, Result}, 13 13 ffi::c_void, 14 14 prelude::*, 15 15 revocable::{Revocable, RevocableGuard}, 16 - sync::{rcu, Arc, Completion}, 17 - types::ARef, 16 + sync::{rcu, Completion}, 17 + types::{ARef, ForeignOwnable, Opaque, ScopeGuard}, 18 18 }; 19 19 20 + use pin_init::Wrapper; 21 + 22 + /// [`Devres`] inner data accessed from [`Devres::callback`]. 20 23 #[pin_data] 21 - struct DevresInner<T> { 22 - dev: ARef<Device>, 23 - callback: unsafe extern "C" fn(*mut c_void), 24 + struct Inner<T: Send> { 24 25 #[pin] 25 26 data: Revocable<T>, 27 + /// Tracks whether [`Devres::callback`] has been completed. 28 + #[pin] 29 + devm: Completion, 30 + /// Tracks whether revoking [`Self::data`] has been completed. 26 31 #[pin] 27 32 revoke: Completion, 28 33 } ··· 52 47 /// # Example 53 48 /// 54 49 /// ```no_run 55 - /// # use kernel::{bindings, c_str, device::{Bound, Device}, devres::Devres, io::{Io, IoRaw}}; 50 + /// # use kernel::{bindings, device::{Bound, Device}, devres::Devres, io::{Io, IoRaw}}; 56 51 /// # use core::ops::Deref; 57 52 /// 58 53 /// // See also [`pci::Bar`] for a real example. ··· 93 88 /// # fn no_run(dev: &Device<Bound>) -> Result<(), Error> { 94 89 /// // SAFETY: Invalid usage for example purposes. 95 90 /// let iomem = unsafe { IoMem::<{ core::mem::size_of::<u32>() }>::new(0xBAAAAAAD)? }; 96 - /// let devres = Devres::new(dev, iomem, GFP_KERNEL)?; 91 + /// let devres = KBox::pin_init(Devres::new(dev, iomem), GFP_KERNEL)?; 97 92 /// 98 93 /// let res = devres.try_access().ok_or(ENXIO)?; 99 94 /// res.write8(0x42, 0x0); 100 95 /// # Ok(()) 101 96 /// # } 102 97 /// ``` 103 - pub struct Devres<T>(Arc<DevresInner<T>>); 98 + /// 99 + /// # Invariants 100 + /// 101 + /// [`Self::inner`] is guaranteed to be initialized and is always accessed read-only. 102 + #[pin_data(PinnedDrop)] 103 + pub struct Devres<T: Send> { 104 + dev: ARef<Device>, 105 + /// Pointer to [`Self::devres_callback`]. 106 + /// 107 + /// Has to be stored, since Rust does not guarantee to always return the same address for a 108 + /// function. However, the C API uses the address as a key. 109 + callback: unsafe extern "C" fn(*mut c_void), 110 + /// Contains all the fields shared with [`Self::callback`]. 111 + // TODO: Replace with `UnsafePinned`, once available. 112 + // 113 + // Subsequently, the `drop_in_place()` in `Devres::drop` and the explicit `Send` and `Sync' 114 + // impls can be removed. 115 + #[pin] 116 + inner: Opaque<Inner<T>>, 117 + } 104 118 105 - impl<T> DevresInner<T> { 106 - fn new(dev: &Device<Bound>, data: T, flags: Flags) -> Result<Arc<DevresInner<T>>> { 107 - let inner = Arc::pin_init( 108 - pin_init!( DevresInner { 109 - dev: dev.into(), 110 - callback: Self::devres_callback, 111 - data <- Revocable::new(data), 112 - revoke <- Completion::new(), 113 - }), 114 - flags, 115 - )?; 119 + impl<T: Send> Devres<T> { 120 + /// Creates a new [`Devres`] instance of the given `data`. 121 + /// 122 + /// The `data` encapsulated within the returned `Devres` instance' `data` will be 123 + /// (revoked)[`Revocable`] once the device is detached. 124 + pub fn new<'a, E>( 125 + dev: &'a Device<Bound>, 126 + data: impl PinInit<T, E> + 'a, 127 + ) -> impl PinInit<Self, Error> + 'a 128 + where 129 + T: 'a, 130 + Error: From<E>, 131 + { 132 + let callback = Self::devres_callback; 116 133 117 - // Convert `Arc<DevresInner>` into a raw pointer and make devres own this reference until 118 - // `Self::devres_callback` is called. 119 - let data = inner.clone().into_raw(); 134 + try_pin_init!(&this in Self { 135 + dev: dev.into(), 136 + callback, 137 + // INVARIANT: `inner` is properly initialized. 138 + inner <- { 139 + // SAFETY: `this` is a valid pointer to uninitialized memory. 140 + let inner = unsafe { &raw mut (*this.as_ptr()).inner }; 120 141 121 - // SAFETY: `devm_add_action` guarantees to call `Self::devres_callback` once `dev` is 122 - // detached. 123 - let ret = 124 - unsafe { bindings::devm_add_action(dev.as_raw(), Some(inner.callback), data as _) }; 142 + // SAFETY: 143 + // - `dev.as_raw()` is a pointer to a valid bound device. 144 + // - `inner` is guaranteed to be a valid for the duration of the lifetime of `Self`. 145 + // - `devm_add_action()` is guaranteed not to call `callback` until `this` has been 146 + // properly initialized, because we require `dev` (i.e. the *bound* device) to 147 + // live at least as long as the returned `impl PinInit<Self, Error>`. 148 + to_result(unsafe { 149 + bindings::devm_add_action(dev.as_raw(), Some(callback), inner.cast()) 150 + })?; 125 151 126 - if ret != 0 { 127 - // SAFETY: We just created another reference to `inner` in order to pass it to 128 - // `bindings::devm_add_action`. If `bindings::devm_add_action` fails, we have to drop 129 - // this reference accordingly. 130 - let _ = unsafe { Arc::from_raw(data) }; 131 - return Err(Error::from_errno(ret)); 132 - } 133 - 134 - Ok(inner) 152 + Opaque::pin_init(try_pin_init!(Inner { 153 + devm <- Completion::new(), 154 + revoke <- Completion::new(), 155 + data <- Revocable::new(data), 156 + })) 157 + }, 158 + }) 135 159 } 136 160 137 - fn as_ptr(&self) -> *const Self { 138 - self as _ 161 + fn inner(&self) -> &Inner<T> { 162 + // SAFETY: By the type invairants of `Self`, `inner` is properly initialized and always 163 + // accessed read-only. 164 + unsafe { &*self.inner.get() } 139 165 } 140 166 141 - fn remove_action(this: &Arc<Self>) -> bool { 142 - // SAFETY: 143 - // - `self.inner.dev` is a valid `Device`, 144 - // - the `action` and `data` pointers are the exact same ones as given to devm_add_action() 145 - // previously, 146 - // - `self` is always valid, even if the action has been released already. 147 - let success = unsafe { 148 - bindings::devm_remove_action_nowarn( 149 - this.dev.as_raw(), 150 - Some(this.callback), 151 - this.as_ptr() as _, 152 - ) 153 - } == 0; 154 - 155 - if success { 156 - // SAFETY: We leaked an `Arc` reference to devm_add_action() in `DevresInner::new`; if 157 - // devm_remove_action_nowarn() was successful we can (and have to) claim back ownership 158 - // of this reference. 159 - let _ = unsafe { Arc::from_raw(this.as_ptr()) }; 160 - } 161 - 162 - success 167 + fn data(&self) -> &Revocable<T> { 168 + &self.inner().data 163 169 } 164 170 165 171 #[allow(clippy::missing_safety_doc)] 166 172 unsafe extern "C" fn devres_callback(ptr: *mut kernel::ffi::c_void) { 167 - let ptr = ptr as *mut DevresInner<T>; 168 - // Devres owned this memory; now that we received the callback, drop the `Arc` and hence the 169 - // reference. 170 - // SAFETY: Safe, since we leaked an `Arc` reference to devm_add_action() in 171 - // `DevresInner::new`. 172 - let inner = unsafe { Arc::from_raw(ptr) }; 173 + // SAFETY: In `Self::new` we've passed a valid pointer to `Inner` to `devm_add_action()`, 174 + // hence `ptr` must be a valid pointer to `Inner`. 175 + let inner = unsafe { &*ptr.cast::<Inner<T>>() }; 176 + 177 + // Ensure that `inner` can't be used anymore after we signal completion of this callback. 178 + let inner = ScopeGuard::new_with_data(inner, |inner| inner.devm.complete_all()); 173 179 174 180 if !inner.data.revoke() { 175 181 // If `revoke()` returns false, it means that `Devres::drop` already started revoking 176 - // `inner.data` for us. Hence we have to wait until `Devres::drop()` signals that it 177 - // completed revoking `inner.data`. 182 + // `data` for us. Hence we have to wait until `Devres::drop` signals that it 183 + // completed revoking `data`. 178 184 inner.revoke.wait_for_completion(); 179 185 } 180 186 } 181 - } 182 187 183 - impl<T> Devres<T> { 184 - /// Creates a new [`Devres`] instance of the given `data`. The `data` encapsulated within the 185 - /// returned `Devres` instance' `data` will be revoked once the device is detached. 186 - pub fn new(dev: &Device<Bound>, data: T, flags: Flags) -> Result<Self> { 187 - let inner = DevresInner::new(dev, data, flags)?; 188 - 189 - Ok(Devres(inner)) 188 + fn remove_action(&self) -> bool { 189 + // SAFETY: 190 + // - `self.dev` is a valid `Device`, 191 + // - the `action` and `data` pointers are the exact same ones as given to 192 + // `devm_add_action()` previously, 193 + (unsafe { 194 + bindings::devm_remove_action_nowarn( 195 + self.dev.as_raw(), 196 + Some(self.callback), 197 + core::ptr::from_ref(self.inner()).cast_mut().cast(), 198 + ) 199 + } == 0) 190 200 } 191 201 192 - /// Same as [`Devres::new`], but does not return a `Devres` instance. Instead the given `data` 193 - /// is owned by devres and will be revoked / dropped, once the device is detached. 194 - pub fn new_foreign_owned(dev: &Device<Bound>, data: T, flags: Flags) -> Result { 195 - let _ = DevresInner::new(dev, data, flags)?; 196 - 197 - Ok(()) 202 + /// Return a reference of the [`Device`] this [`Devres`] instance has been created with. 203 + pub fn device(&self) -> &Device { 204 + &self.dev 198 205 } 199 206 200 207 /// Obtain `&'a T`, bypassing the [`Revocable`]. ··· 238 221 /// } 239 222 /// ``` 240 223 pub fn access<'a>(&'a self, dev: &'a Device<Bound>) -> Result<&'a T> { 241 - if self.0.dev.as_raw() != dev.as_raw() { 224 + if self.dev.as_raw() != dev.as_raw() { 242 225 return Err(EINVAL); 243 226 } 244 227 245 228 // SAFETY: `dev` being the same device as the device this `Devres` has been created for 246 - // proves that `self.0.data` hasn't been revoked and is guaranteed to not be revoked as 247 - // long as `dev` lives; `dev` lives at least as long as `self`. 248 - Ok(unsafe { self.0.data.access() }) 229 + // proves that `self.data` hasn't been revoked and is guaranteed to not be revoked as long 230 + // as `dev` lives; `dev` lives at least as long as `self`. 231 + Ok(unsafe { self.data().access() }) 249 232 } 250 233 251 234 /// [`Devres`] accessor for [`Revocable::try_access`]. 252 235 pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> { 253 - self.0.data.try_access() 236 + self.data().try_access() 254 237 } 255 238 256 239 /// [`Devres`] accessor for [`Revocable::try_access_with`]. 257 240 pub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R> { 258 - self.0.data.try_access_with(f) 241 + self.data().try_access_with(f) 259 242 } 260 243 261 244 /// [`Devres`] accessor for [`Revocable::try_access_with_guard`]. 262 245 pub fn try_access_with_guard<'a>(&'a self, guard: &'a rcu::Guard) -> Option<&'a T> { 263 - self.0.data.try_access_with_guard(guard) 246 + self.data().try_access_with_guard(guard) 264 247 } 265 248 } 266 249 267 - impl<T> Drop for Devres<T> { 268 - fn drop(&mut self) { 250 + // SAFETY: `Devres` can be send to any task, if `T: Send`. 251 + unsafe impl<T: Send> Send for Devres<T> {} 252 + 253 + // SAFETY: `Devres` can be shared with any task, if `T: Sync`. 254 + unsafe impl<T: Send + Sync> Sync for Devres<T> {} 255 + 256 + #[pinned_drop] 257 + impl<T: Send> PinnedDrop for Devres<T> { 258 + fn drop(self: Pin<&mut Self>) { 269 259 // SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data 270 260 // anymore, hence it is safe not to wait for the grace period to finish. 271 - if unsafe { self.0.data.revoke_nosync() } { 272 - // We revoked `self.0.data` before the devres action did, hence try to remove it. 273 - if !DevresInner::remove_action(&self.0) { 261 + if unsafe { self.data().revoke_nosync() } { 262 + // We revoked `self.data` before the devres action did, hence try to remove it. 263 + if !self.remove_action() { 274 264 // We could not remove the devres action, which means that it now runs concurrently, 275 - // hence signal that `self.0.data` has been revoked successfully. 276 - self.0.revoke.complete_all(); 265 + // hence signal that `self.data` has been revoked by us successfully. 266 + self.inner().revoke.complete_all(); 267 + 268 + // Wait for `Self::devres_callback` to be done using this object. 269 + self.inner().devm.wait_for_completion(); 277 270 } 271 + } else { 272 + // `Self::devres_callback` revokes `self.data` for us, hence wait for it to be done 273 + // using this object. 274 + self.inner().devm.wait_for_completion(); 278 275 } 276 + 277 + // INVARIANT: At this point it is guaranteed that `inner` can't be accessed any more. 278 + // 279 + // SAFETY: `inner` is valid for dropping. 280 + unsafe { core::ptr::drop_in_place(self.inner.get()) }; 279 281 } 282 + } 283 + 284 + /// Consume `data` and [`Drop::drop`] `data` once `dev` is unbound. 285 + fn register_foreign<P>(dev: &Device<Bound>, data: P) -> Result 286 + where 287 + P: ForeignOwnable + Send + 'static, 288 + { 289 + let ptr = data.into_foreign(); 290 + 291 + #[allow(clippy::missing_safety_doc)] 292 + unsafe extern "C" fn callback<P: ForeignOwnable>(ptr: *mut kernel::ffi::c_void) { 293 + // SAFETY: `ptr` is the pointer to the `ForeignOwnable` leaked above and hence valid. 294 + drop(unsafe { P::from_foreign(ptr.cast()) }); 295 + } 296 + 297 + // SAFETY: 298 + // - `dev.as_raw()` is a pointer to a valid and bound device. 299 + // - `ptr` is a valid pointer the `ForeignOwnable` devres takes ownership of. 300 + to_result(unsafe { 301 + // `devm_add_action_or_reset()` also calls `callback` on failure, such that the 302 + // `ForeignOwnable` is released eventually. 303 + bindings::devm_add_action_or_reset(dev.as_raw(), Some(callback::<P>), ptr.cast()) 304 + }) 305 + } 306 + 307 + /// Encapsulate `data` in a [`KBox`] and [`Drop::drop`] `data` once `dev` is unbound. 308 + /// 309 + /// # Examples 310 + /// 311 + /// ```no_run 312 + /// use kernel::{device::{Bound, Device}, devres}; 313 + /// 314 + /// /// Registration of e.g. a class device, IRQ, etc. 315 + /// struct Registration; 316 + /// 317 + /// impl Registration { 318 + /// fn new() -> Self { 319 + /// // register 320 + /// 321 + /// Self 322 + /// } 323 + /// } 324 + /// 325 + /// impl Drop for Registration { 326 + /// fn drop(&mut self) { 327 + /// // unregister 328 + /// } 329 + /// } 330 + /// 331 + /// fn from_bound_context(dev: &Device<Bound>) -> Result { 332 + /// devres::register(dev, Registration::new(), GFP_KERNEL) 333 + /// } 334 + /// ``` 335 + pub fn register<T, E>(dev: &Device<Bound>, data: impl PinInit<T, E>, flags: Flags) -> Result 336 + where 337 + T: Send + 'static, 338 + Error: From<E>, 339 + { 340 + let data = KBox::pin_init(data, flags)?; 341 + 342 + register_foreign(dev, data) 280 343 }
+149 -7
rust/kernel/dma.rs
··· 5 5 //! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h) 6 6 7 7 use crate::{ 8 - bindings, build_assert, 9 - device::{Bound, Device}, 10 - error::code::*, 11 - error::Result, 8 + bindings, build_assert, device, 9 + device::{Bound, Core}, 10 + error::{to_result, Result}, 11 + prelude::*, 12 12 transmute::{AsBytes, FromBytes}, 13 13 types::ARef, 14 14 }; 15 + 16 + /// Trait to be implemented by DMA capable bus devices. 17 + /// 18 + /// The [`dma::Device`](Device) trait should be implemented by bus specific device representations, 19 + /// where the underlying bus is DMA capable, such as [`pci::Device`](::kernel::pci::Device) or 20 + /// [`platform::Device`](::kernel::platform::Device). 21 + pub trait Device: AsRef<device::Device<Core>> { 22 + /// Set up the device's DMA streaming addressing capabilities. 23 + /// 24 + /// This method is usually called once from `probe()` as soon as the device capabilities are 25 + /// known. 26 + /// 27 + /// # Safety 28 + /// 29 + /// This method must not be called concurrently with any DMA allocation or mapping primitives, 30 + /// such as [`CoherentAllocation::alloc_attrs`]. 31 + unsafe fn dma_set_mask(&self, mask: DmaMask) -> Result { 32 + // SAFETY: 33 + // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. 34 + // - The safety requirement of this function guarantees that there are no concurrent calls 35 + // to DMA allocation and mapping primitives using this mask. 36 + to_result(unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask.value()) }) 37 + } 38 + 39 + /// Set up the device's DMA coherent addressing capabilities. 40 + /// 41 + /// This method is usually called once from `probe()` as soon as the device capabilities are 42 + /// known. 43 + /// 44 + /// # Safety 45 + /// 46 + /// This method must not be called concurrently with any DMA allocation or mapping primitives, 47 + /// such as [`CoherentAllocation::alloc_attrs`]. 48 + unsafe fn dma_set_coherent_mask(&self, mask: DmaMask) -> Result { 49 + // SAFETY: 50 + // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. 51 + // - The safety requirement of this function guarantees that there are no concurrent calls 52 + // to DMA allocation and mapping primitives using this mask. 53 + to_result(unsafe { bindings::dma_set_coherent_mask(self.as_ref().as_raw(), mask.value()) }) 54 + } 55 + 56 + /// Set up the device's DMA addressing capabilities. 57 + /// 58 + /// This is a combination of [`Device::dma_set_mask`] and [`Device::dma_set_coherent_mask`]. 59 + /// 60 + /// This method is usually called once from `probe()` as soon as the device capabilities are 61 + /// known. 62 + /// 63 + /// # Safety 64 + /// 65 + /// This method must not be called concurrently with any DMA allocation or mapping primitives, 66 + /// such as [`CoherentAllocation::alloc_attrs`]. 67 + unsafe fn dma_set_mask_and_coherent(&self, mask: DmaMask) -> Result { 68 + // SAFETY: 69 + // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. 70 + // - The safety requirement of this function guarantees that there are no concurrent calls 71 + // to DMA allocation and mapping primitives using this mask. 72 + to_result(unsafe { 73 + bindings::dma_set_mask_and_coherent(self.as_ref().as_raw(), mask.value()) 74 + }) 75 + } 76 + } 77 + 78 + /// A DMA mask that holds a bitmask with the lowest `n` bits set. 79 + /// 80 + /// Use [`DmaMask::new`] or [`DmaMask::try_new`] to construct a value. Values 81 + /// are guaranteed to never exceed the bit width of `u64`. 82 + /// 83 + /// This is the Rust equivalent of the C macro `DMA_BIT_MASK()`. 84 + #[derive(Debug, Clone, Copy, PartialEq, Eq)] 85 + pub struct DmaMask(u64); 86 + 87 + impl DmaMask { 88 + /// Constructs a `DmaMask` with the lowest `n` bits set to `1`. 89 + /// 90 + /// For `n <= 64`, sets exactly the lowest `n` bits. 91 + /// For `n > 64`, results in a build error. 92 + /// 93 + /// # Examples 94 + /// 95 + /// ``` 96 + /// use kernel::dma::DmaMask; 97 + /// 98 + /// let mask0 = DmaMask::new::<0>(); 99 + /// assert_eq!(mask0.value(), 0); 100 + /// 101 + /// let mask1 = DmaMask::new::<1>(); 102 + /// assert_eq!(mask1.value(), 0b1); 103 + /// 104 + /// let mask64 = DmaMask::new::<64>(); 105 + /// assert_eq!(mask64.value(), u64::MAX); 106 + /// 107 + /// // Build failure. 108 + /// // let mask_overflow = DmaMask::new::<100>(); 109 + /// ``` 110 + #[inline] 111 + pub const fn new<const N: u32>() -> Self { 112 + let Ok(mask) = Self::try_new(N) else { 113 + build_error!("Invalid DMA Mask."); 114 + }; 115 + 116 + mask 117 + } 118 + 119 + /// Constructs a `DmaMask` with the lowest `n` bits set to `1`. 120 + /// 121 + /// For `n <= 64`, sets exactly the lowest `n` bits. 122 + /// For `n > 64`, returns [`EINVAL`]. 123 + /// 124 + /// # Examples 125 + /// 126 + /// ``` 127 + /// use kernel::dma::DmaMask; 128 + /// 129 + /// let mask0 = DmaMask::try_new(0)?; 130 + /// assert_eq!(mask0.value(), 0); 131 + /// 132 + /// let mask1 = DmaMask::try_new(1)?; 133 + /// assert_eq!(mask1.value(), 0b1); 134 + /// 135 + /// let mask64 = DmaMask::try_new(64)?; 136 + /// assert_eq!(mask64.value(), u64::MAX); 137 + /// 138 + /// let mask_overflow = DmaMask::try_new(100); 139 + /// assert!(mask_overflow.is_err()); 140 + /// # Ok::<(), Error>(()) 141 + /// ``` 142 + #[inline] 143 + pub const fn try_new(n: u32) -> Result<Self> { 144 + Ok(Self(match n { 145 + 0 => 0, 146 + 1..=64 => u64::MAX >> (64 - n), 147 + _ => return Err(EINVAL), 148 + })) 149 + } 150 + 151 + /// Returns the underlying `u64` bitmask value. 152 + #[inline] 153 + pub const fn value(&self) -> u64 { 154 + self.0 155 + } 156 + } 15 157 16 158 /// Possible attributes associated with a DMA mapping. 17 159 /// ··· 272 130 // Hence, find a way to revoke the device resources of a `CoherentAllocation`, but not the 273 131 // entire `CoherentAllocation` including the allocated memory itself. 274 132 pub struct CoherentAllocation<T: AsBytes + FromBytes> { 275 - dev: ARef<Device>, 133 + dev: ARef<device::Device>, 276 134 dma_handle: bindings::dma_addr_t, 277 135 count: usize, 278 136 cpu_addr: *mut T, ··· 294 152 /// # Ok::<(), Error>(()) } 295 153 /// ``` 296 154 pub fn alloc_attrs( 297 - dev: &Device<Bound>, 155 + dev: &device::Device<Bound>, 298 156 count: usize, 299 157 gfp_flags: kernel::alloc::Flags, 300 158 dma_attrs: Attrs, ··· 336 194 /// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the 337 195 /// `dma_attrs` is 0 by default. 338 196 pub fn alloc_coherent( 339 - dev: &Device<Bound>, 197 + dev: &device::Device<Bound>, 340 198 count: usize, 341 199 gfp_flags: kernel::alloc::Flags, 342 200 ) -> Result<CoherentAllocation<T>> {
+66 -21
rust/kernel/driver.rs
··· 6 6 //! register using the [`Registration`] class. 7 7 8 8 use crate::error::{Error, Result}; 9 - use crate::{device, of, str::CStr, try_pin_init, types::Opaque, ThisModule}; 9 + use crate::{acpi, device, of, str::CStr, try_pin_init, types::Opaque, ThisModule}; 10 10 use core::pin::Pin; 11 11 use pin_init::{pin_data, pinned_drop, PinInit}; 12 12 ··· 141 141 /// The type holding driver private data about each device id supported by the driver. 142 142 type IdInfo: 'static; 143 143 144 + /// The [`acpi::IdTable`] of the corresponding driver 145 + fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>>; 146 + 147 + /// Returns the driver's private data from the matching entry in the [`acpi::IdTable`], if any. 148 + /// 149 + /// If this returns `None`, it means there is no match with an entry in the [`acpi::IdTable`]. 150 + fn acpi_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> { 151 + #[cfg(not(CONFIG_ACPI))] 152 + { 153 + let _ = dev; 154 + None 155 + } 156 + 157 + #[cfg(CONFIG_ACPI)] 158 + { 159 + let table = Self::acpi_id_table()?; 160 + 161 + // SAFETY: 162 + // - `table` has static lifetime, hence it's valid for read, 163 + // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`. 164 + let raw_id = unsafe { bindings::acpi_match_device(table.as_ptr(), dev.as_raw()) }; 165 + 166 + if raw_id.is_null() { 167 + None 168 + } else { 169 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct acpi_device_id` 170 + // and does not add additional invariants, so it's safe to transmute. 171 + let id = unsafe { &*raw_id.cast::<acpi::DeviceId>() }; 172 + 173 + Some(table.info(<acpi::DeviceId as crate::device_id::RawDeviceIdIndex>::index(id))) 174 + } 175 + } 176 + } 177 + 144 178 /// The [`of::IdTable`] of the corresponding driver. 145 179 fn of_id_table() -> Option<of::IdTable<Self::IdInfo>>; 146 180 147 181 /// Returns the driver's private data from the matching entry in the [`of::IdTable`], if any. 148 182 /// 149 183 /// If this returns `None`, it means there is no match with an entry in the [`of::IdTable`]. 150 - #[cfg(CONFIG_OF)] 151 184 fn of_id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> { 152 - let table = Self::of_id_table()?; 153 - 154 - // SAFETY: 155 - // - `table` has static lifetime, hence it's valid for read, 156 - // - `dev` is guaranteed to be valid while it's alive, and so is `pdev.as_ref().as_raw()`. 157 - let raw_id = unsafe { bindings::of_match_device(table.as_ptr(), dev.as_raw()) }; 158 - 159 - if raw_id.is_null() { 185 + #[cfg(not(CONFIG_OF))] 186 + { 187 + let _ = dev; 160 188 None 161 - } else { 162 - // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct of_device_id` and 163 - // does not add additional invariants, so it's safe to transmute. 164 - let id = unsafe { &*raw_id.cast::<of::DeviceId>() }; 165 - 166 - Some(table.info(<of::DeviceId as crate::device_id::RawDeviceId>::index(id))) 167 189 } 168 - } 169 190 170 - #[cfg(not(CONFIG_OF))] 171 - #[allow(missing_docs)] 172 - fn of_id_info(_dev: &device::Device) -> Option<&'static Self::IdInfo> { 173 - None 191 + #[cfg(CONFIG_OF)] 192 + { 193 + let table = Self::of_id_table()?; 194 + 195 + // SAFETY: 196 + // - `table` has static lifetime, hence it's valid for read, 197 + // - `dev` is guaranteed to be valid while it's alive, and so is `dev.as_raw()`. 198 + let raw_id = unsafe { bindings::of_match_device(table.as_ptr(), dev.as_raw()) }; 199 + 200 + if raw_id.is_null() { 201 + None 202 + } else { 203 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id` 204 + // and does not add additional invariants, so it's safe to transmute. 205 + let id = unsafe { &*raw_id.cast::<of::DeviceId>() }; 206 + 207 + Some( 208 + table.info(<of::DeviceId as crate::device_id::RawDeviceIdIndex>::index( 209 + id, 210 + )), 211 + ) 212 + } 213 + } 174 214 } 175 215 176 216 /// Returns the driver's private data from the matching entry of any of the ID tables, if any. ··· 218 178 /// If this returns `None`, it means that there is no match in any of the ID tables directly 219 179 /// associated with a [`device::Device`]. 220 180 fn id_info(dev: &device::Device) -> Option<&'static Self::IdInfo> { 181 + let id = Self::acpi_id_info(dev); 182 + if id.is_some() { 183 + return id; 184 + } 185 + 221 186 let id = Self::of_id_info(dev); 222 187 if id.is_some() { 223 188 return id;
+1 -1
rust/kernel/drm/device.rs
··· 200 200 fn as_ref(&self) -> &device::Device { 201 201 // SAFETY: `bindings::drm_device::dev` is valid as long as the DRM device itself is valid, 202 202 // which is guaranteed by the type invariant. 203 - unsafe { device::Device::as_ref((*self.as_raw()).dev) } 203 + unsafe { device::Device::from_raw((*self.as_raw()).dev) } 204 204 } 205 205 } 206 206
+8 -6
rust/kernel/drm/driver.rs
··· 5 5 //! C header: [`include/linux/drm/drm_drv.h`](srctree/include/linux/drm/drm_drv.h) 6 6 7 7 use crate::{ 8 - bindings, device, 9 - devres::Devres, 10 - drm, 8 + bindings, device, devres, drm, 11 9 error::{to_result, Result}, 12 10 prelude::*, 13 11 types::ARef, ··· 127 129 } 128 130 129 131 /// Same as [`Registration::new`}, but transfers ownership of the [`Registration`] to 130 - /// [`Devres`]. 132 + /// [`devres::register`]. 131 133 pub fn new_foreign_owned( 132 134 drm: &drm::Device<T>, 133 135 dev: &device::Device<device::Bound>, 134 136 flags: usize, 135 - ) -> Result { 137 + ) -> Result 138 + where 139 + T: 'static, 140 + { 136 141 if drm.as_ref().as_raw() != dev.as_raw() { 137 142 return Err(EINVAL); 138 143 } 139 144 140 145 let reg = Registration::<T>::new(drm, flags)?; 141 - Devres::new_foreign_owned(dev, reg, GFP_KERNEL) 146 + 147 + devres::register(dev, reg, GFP_KERNEL) 142 148 } 143 149 144 150 /// Returns a reference to the `Device` instance for this registration.
+1 -1
rust/kernel/faux.rs
··· 54 54 fn as_ref(&self) -> &device::Device { 55 55 // SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be 56 56 // a valid initialized `device`. 57 - unsafe { device::Device::as_ref(addr_of_mut!((*self.as_raw()).dev)) } 57 + unsafe { device::Device::from_raw(addr_of_mut!((*self.as_raw()).dev)) } 58 58 } 59 59 } 60 60
+5
rust/kernel/io.rs
··· 7 7 use crate::error::{code::EINVAL, Result}; 8 8 use crate::{bindings, build_assert}; 9 9 10 + pub mod mem; 11 + pub mod resource; 12 + 13 + pub use resource::Resource; 14 + 10 15 /// Raw representation of an MMIO region. 11 16 /// 12 17 /// By itself, the existence of an instance of this structure does not provide any guarantees that
+279
rust/kernel/io/mem.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Generic memory-mapped IO. 4 + 5 + use core::ops::Deref; 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::*; 17 + 18 + /// An IO request for a specific device and resource. 19 + pub struct IoRequest<'a> { 20 + device: &'a Device<Bound>, 21 + resource: &'a Resource, 22 + } 23 + 24 + impl<'a> IoRequest<'a> { 25 + /// Creates a new [`IoRequest`] instance. 26 + /// 27 + /// # Safety 28 + /// 29 + /// Callers must ensure that `resource` is valid for `device` during the 30 + /// lifetime `'a`. 31 + pub(crate) unsafe fn new(device: &'a Device<Bound>, resource: &'a Resource) -> Self { 32 + IoRequest { device, resource } 33 + } 34 + 35 + /// Maps an [`IoRequest`] where the size is known at compile time. 36 + /// 37 + /// This uses the [`ioremap()`] C API. 38 + /// 39 + /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device 40 + /// 41 + /// # Examples 42 + /// 43 + /// The following example uses a [`kernel::platform::Device`] for 44 + /// illustration purposes. 45 + /// 46 + /// ```no_run 47 + /// use kernel::{bindings, c_str, platform, of, device::Core}; 48 + /// struct SampleDriver; 49 + /// 50 + /// impl platform::Driver for SampleDriver { 51 + /// # type IdInfo = (); 52 + /// 53 + /// fn probe( 54 + /// pdev: &platform::Device<Core>, 55 + /// info: Option<&Self::IdInfo>, 56 + /// ) -> Result<Pin<KBox<Self>>> { 57 + /// let offset = 0; // Some offset. 58 + /// 59 + /// // If the size is known at compile time, use [`Self::iomap_sized`]. 60 + /// // 61 + /// // No runtime checks will apply when reading and writing. 62 + /// let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; 63 + /// let iomem = request.iomap_sized::<42>(); 64 + /// let iomem = KBox::pin_init(iomem, GFP_KERNEL)?; 65 + /// 66 + /// let io = iomem.access(pdev.as_ref())?; 67 + /// 68 + /// // Read and write a 32-bit value at `offset`. 69 + /// let data = io.read32_relaxed(offset); 70 + /// 71 + /// io.write32_relaxed(data, offset); 72 + /// 73 + /// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) 74 + /// } 75 + /// } 76 + /// ``` 77 + pub fn iomap_sized<const SIZE: usize>(self) -> impl PinInit<Devres<IoMem<SIZE>>, Error> + 'a { 78 + IoMem::new(self) 79 + } 80 + 81 + /// Same as [`Self::iomap_sized`] but with exclusive access to the 82 + /// underlying region. 83 + /// 84 + /// This uses the [`ioremap()`] C API. 85 + /// 86 + /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device 87 + pub fn iomap_exclusive_sized<const SIZE: usize>( 88 + self, 89 + ) -> impl PinInit<Devres<ExclusiveIoMem<SIZE>>, Error> + 'a { 90 + ExclusiveIoMem::new(self) 91 + } 92 + 93 + /// Maps an [`IoRequest`] where the size is not known at compile time, 94 + /// 95 + /// This uses the [`ioremap()`] C API. 96 + /// 97 + /// [`ioremap()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device 98 + /// 99 + /// # Examples 100 + /// 101 + /// The following example uses a [`kernel::platform::Device`] for 102 + /// illustration purposes. 103 + /// 104 + /// ```no_run 105 + /// use kernel::{bindings, c_str, platform, of, device::Core}; 106 + /// struct SampleDriver; 107 + /// 108 + /// impl platform::Driver for SampleDriver { 109 + /// # type IdInfo = (); 110 + /// 111 + /// fn probe( 112 + /// pdev: &platform::Device<Core>, 113 + /// info: Option<&Self::IdInfo>, 114 + /// ) -> Result<Pin<KBox<Self>>> { 115 + /// let offset = 0; // Some offset. 116 + /// 117 + /// // Unlike [`Self::iomap_sized`], here the size of the memory region 118 + /// // is not known at compile time, so only the `try_read*` and `try_write*` 119 + /// // family of functions should be used, leading to runtime checks on every 120 + /// // access. 121 + /// let request = pdev.io_request_by_index(0).ok_or(ENODEV)?; 122 + /// let iomem = request.iomap(); 123 + /// let iomem = KBox::pin_init(iomem, GFP_KERNEL)?; 124 + /// 125 + /// let io = iomem.access(pdev.as_ref())?; 126 + /// 127 + /// let data = io.try_read32_relaxed(offset)?; 128 + /// 129 + /// io.try_write32_relaxed(data, offset)?; 130 + /// 131 + /// # Ok(KBox::new(SampleDriver, GFP_KERNEL)?.into()) 132 + /// } 133 + /// } 134 + /// ``` 135 + pub fn iomap(self) -> impl PinInit<Devres<IoMem<0>>, Error> + 'a { 136 + Self::iomap_sized::<0>(self) 137 + } 138 + 139 + /// Same as [`Self::iomap`] but with exclusive access to the underlying 140 + /// region. 141 + pub fn iomap_exclusive(self) -> impl PinInit<Devres<ExclusiveIoMem<0>>, Error> + 'a { 142 + Self::iomap_exclusive_sized::<0>(self) 143 + } 144 + } 145 + 146 + /// An exclusive memory-mapped IO region. 147 + /// 148 + /// # Invariants 149 + /// 150 + /// - [`ExclusiveIoMem`] has exclusive access to the underlying [`IoMem`]. 151 + pub struct ExclusiveIoMem<const SIZE: usize> { 152 + /// The underlying `IoMem` instance. 153 + iomem: IoMem<SIZE>, 154 + 155 + /// The region abstraction. This represents exclusive access to the 156 + /// range represented by the underlying `iomem`. 157 + /// 158 + /// This field is needed for ownership of the region. 159 + _region: Region, 160 + } 161 + 162 + impl<const SIZE: usize> ExclusiveIoMem<SIZE> { 163 + /// Creates a new `ExclusiveIoMem` instance. 164 + fn ioremap(resource: &Resource) -> Result<Self> { 165 + let start = resource.start(); 166 + let size = resource.size(); 167 + let name = resource.name().unwrap_or(c_str!("")); 168 + 169 + let region = resource 170 + .request_region( 171 + start, 172 + size, 173 + name.to_cstring()?, 174 + io::resource::Flags::IORESOURCE_MEM, 175 + ) 176 + .ok_or(EBUSY)?; 177 + 178 + let iomem = IoMem::ioremap(resource)?; 179 + 180 + let iomem = ExclusiveIoMem { 181 + iomem, 182 + _region: region, 183 + }; 184 + 185 + Ok(iomem) 186 + } 187 + 188 + /// Creates a new `ExclusiveIoMem` instance from a previously acquired [`IoRequest`]. 189 + pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> + 'a { 190 + let dev = io_request.device; 191 + let res = io_request.resource; 192 + 193 + Devres::new(dev, Self::ioremap(res)) 194 + } 195 + } 196 + 197 + impl<const SIZE: usize> Deref for ExclusiveIoMem<SIZE> { 198 + type Target = Io<SIZE>; 199 + 200 + fn deref(&self) -> &Self::Target { 201 + &self.iomem 202 + } 203 + } 204 + 205 + /// A generic memory-mapped IO region. 206 + /// 207 + /// Accesses to the underlying region is checked either at compile time, if the 208 + /// region's size is known at that point, or at runtime otherwise. 209 + /// 210 + /// # Invariants 211 + /// 212 + /// [`IoMem`] always holds an [`IoRaw`] instance that holds a valid pointer to the 213 + /// start of the I/O memory mapped region. 214 + pub struct IoMem<const SIZE: usize = 0> { 215 + io: IoRaw<SIZE>, 216 + } 217 + 218 + impl<const SIZE: usize> IoMem<SIZE> { 219 + fn ioremap(resource: &Resource) -> Result<Self> { 220 + // Note: Some ioremap() implementations use types that depend on the CPU 221 + // word width rather than the bus address width. 222 + // 223 + // TODO: Properly address this in the C code to avoid this `try_into`. 224 + let size = resource.size().try_into()?; 225 + if size == 0 { 226 + return Err(EINVAL); 227 + } 228 + 229 + let res_start = resource.start(); 230 + 231 + let addr = if resource 232 + .flags() 233 + .contains(io::resource::Flags::IORESOURCE_MEM_NONPOSTED) 234 + { 235 + // SAFETY: 236 + // - `res_start` and `size` are read from a presumably valid `struct resource`. 237 + // - `size` is known not to be zero at this point. 238 + unsafe { bindings::ioremap_np(res_start, size) } 239 + } else { 240 + // SAFETY: 241 + // - `res_start` and `size` are read from a presumably valid `struct resource`. 242 + // - `size` is known not to be zero at this point. 243 + unsafe { bindings::ioremap(res_start, size) } 244 + }; 245 + 246 + if addr.is_null() { 247 + return Err(ENOMEM); 248 + } 249 + 250 + let io = IoRaw::new(addr as usize, size)?; 251 + let io = IoMem { io }; 252 + 253 + Ok(io) 254 + } 255 + 256 + /// Creates a new `IoMem` instance from a previously acquired [`IoRequest`]. 257 + pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> + 'a { 258 + let dev = io_request.device; 259 + let res = io_request.resource; 260 + 261 + Devres::new(dev, Self::ioremap(res)) 262 + } 263 + } 264 + 265 + impl<const SIZE: usize> Drop for IoMem<SIZE> { 266 + fn drop(&mut self) { 267 + // SAFETY: Safe as by the invariant of `Io`. 268 + unsafe { bindings::iounmap(self.io.addr() as *mut c_void) } 269 + } 270 + } 271 + 272 + impl<const SIZE: usize> Deref for IoMem<SIZE> { 273 + type Target = Io<SIZE>; 274 + 275 + fn deref(&self) -> &Self::Target { 276 + // SAFETY: Safe as by the invariant of `IoMem`. 277 + unsafe { Io::from_raw(&self.io) } 278 + } 279 + }
+230
rust/kernel/io/resource.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Abstractions for [system 4 + //! resources](https://docs.kernel.org/core-api/kernel-api.html#resources-management). 5 + //! 6 + //! C header: [`include/linux/ioport.h`](srctree/include/linux/ioport.h) 7 + 8 + use core::ops::Deref; 9 + use core::ptr::NonNull; 10 + 11 + use crate::prelude::*; 12 + use crate::str::{CStr, CString}; 13 + use crate::types::Opaque; 14 + 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; 20 + 21 + /// A region allocated from a parent [`Resource`]. 22 + /// 23 + /// # Invariants 24 + /// 25 + /// - `self.0` points to a valid `bindings::resource` that was obtained through 26 + /// `bindings::__request_region`. 27 + pub struct Region { 28 + /// The resource returned when the region was requested. 29 + resource: NonNull<bindings::resource>, 30 + /// The name that was passed in when the region was requested. We need to 31 + /// store it for ownership reasons. 32 + _name: CString, 33 + } 34 + 35 + impl Deref for Region { 36 + type Target = Resource; 37 + 38 + fn deref(&self) -> &Self::Target { 39 + // SAFETY: Safe as per the invariant of `Region`. 40 + unsafe { Resource::from_raw(self.resource.as_ptr()) } 41 + } 42 + } 43 + 44 + impl Drop for Region { 45 + fn drop(&mut self) { 46 + let (flags, start, size) = { 47 + let res = &**self; 48 + (res.flags(), res.start(), res.size()) 49 + }; 50 + 51 + let release_fn = if flags.contains(Flags::IORESOURCE_MEM) { 52 + bindings::release_mem_region 53 + } else { 54 + bindings::release_region 55 + }; 56 + 57 + // SAFETY: Safe as per the invariant of `Region`. 58 + unsafe { release_fn(start, size) }; 59 + } 60 + } 61 + 62 + // SAFETY: `Region` only holds a pointer to a C `struct resource`, which is safe to be used from 63 + // any thread. 64 + unsafe impl Send for Region {} 65 + 66 + // SAFETY: `Region` only holds a pointer to a C `struct resource`, references to which are 67 + // safe to be used from any thread. 68 + unsafe impl Sync for Region {} 69 + 70 + /// A resource abstraction. 71 + /// 72 + /// # Invariants 73 + /// 74 + /// [`Resource`] is a transparent wrapper around a valid `bindings::resource`. 75 + #[repr(transparent)] 76 + pub struct Resource(Opaque<bindings::resource>); 77 + 78 + impl Resource { 79 + /// Creates a reference to a [`Resource`] from a valid pointer. 80 + /// 81 + /// # Safety 82 + /// 83 + /// The caller must ensure that for the duration of 'a, the pointer will 84 + /// point at a valid `bindings::resource`. 85 + /// 86 + /// The caller must also ensure that the [`Resource`] is only accessed via the 87 + /// returned reference for the duration of 'a. 88 + pub(crate) const unsafe fn from_raw<'a>(ptr: *mut bindings::resource) -> &'a Self { 89 + // SAFETY: Self is a transparent wrapper around `Opaque<bindings::resource>`. 90 + unsafe { &*ptr.cast() } 91 + } 92 + 93 + /// Requests a resource region. 94 + /// 95 + /// Exclusive access will be given and the region will be marked as busy. 96 + /// Further calls to [`Self::request_region`] will return [`None`] if 97 + /// the region, or a part of it, is already in use. 98 + pub fn request_region( 99 + &self, 100 + start: ResourceSize, 101 + size: ResourceSize, 102 + name: CString, 103 + flags: Flags, 104 + ) -> Option<Region> { 105 + // SAFETY: 106 + // - Safe as per the invariant of `Resource`. 107 + // - `__request_region` will store a reference to the name, but that is 108 + // safe as we own it and it will not be dropped until the `Region` is 109 + // dropped. 110 + let region = unsafe { 111 + bindings::__request_region( 112 + self.0.get(), 113 + start, 114 + size, 115 + name.as_char_ptr(), 116 + flags.0 as c_int, 117 + ) 118 + }; 119 + 120 + Some(Region { 121 + resource: NonNull::new(region)?, 122 + _name: name, 123 + }) 124 + } 125 + 126 + /// Returns the size of the resource. 127 + pub fn size(&self) -> ResourceSize { 128 + let inner = self.0.get(); 129 + // SAFETY: Safe as per the invariants of `Resource`. 130 + unsafe { bindings::resource_size(inner) } 131 + } 132 + 133 + /// Returns the start address of the resource. 134 + pub fn start(&self) -> ResourceSize { 135 + let inner = self.0.get(); 136 + // SAFETY: Safe as per the invariants of `Resource`. 137 + unsafe { (*inner).start } 138 + } 139 + 140 + /// Returns the name of the resource. 141 + pub fn name(&self) -> Option<&CStr> { 142 + let inner = self.0.get(); 143 + 144 + // SAFETY: Safe as per the invariants of `Resource`. 145 + let name = unsafe { (*inner).name }; 146 + 147 + if name.is_null() { 148 + return None; 149 + } 150 + 151 + // SAFETY: In the C code, `resource::name` either contains a null 152 + // pointer or points to a valid NUL-terminated C string, and at this 153 + // point we know it is not null, so we can safely convert it to a 154 + // `CStr`. 155 + Some(unsafe { CStr::from_char_ptr(name) }) 156 + } 157 + 158 + /// Returns the flags associated with the resource. 159 + pub fn flags(&self) -> Flags { 160 + let inner = self.0.get(); 161 + // SAFETY: Safe as per the invariants of `Resource`. 162 + let flags = unsafe { (*inner).flags }; 163 + 164 + Flags(flags) 165 + } 166 + } 167 + 168 + // SAFETY: `Resource` only holds a pointer to a C `struct resource`, which is 169 + // safe to be used from any thread. 170 + unsafe impl Send for Resource {} 171 + 172 + // SAFETY: `Resource` only holds a pointer to a C `struct resource`, references 173 + // to which are safe to be used from any thread. 174 + unsafe impl Sync for Resource {} 175 + 176 + /// Resource flags as stored in the C `struct resource::flags` field. 177 + /// 178 + /// They can be combined with the operators `|`, `&`, and `!`. 179 + /// 180 + /// Values can be used from the associated constants such as 181 + /// [`Flags::IORESOURCE_IO`]. 182 + #[derive(Clone, Copy, PartialEq)] 183 + pub struct Flags(c_ulong); 184 + 185 + impl Flags { 186 + /// Check whether `flags` is contained in `self`. 187 + pub fn contains(self, flags: Flags) -> bool { 188 + (self & flags) == flags 189 + } 190 + } 191 + 192 + impl core::ops::BitOr for Flags { 193 + type Output = Self; 194 + fn bitor(self, rhs: Self) -> Self::Output { 195 + Self(self.0 | rhs.0) 196 + } 197 + } 198 + 199 + impl core::ops::BitAnd for Flags { 200 + type Output = Self; 201 + fn bitand(self, rhs: Self) -> Self::Output { 202 + Self(self.0 & rhs.0) 203 + } 204 + } 205 + 206 + impl core::ops::Not for Flags { 207 + type Output = Self; 208 + fn not(self) -> Self::Output { 209 + Self(!self.0) 210 + } 211 + } 212 + 213 + impl Flags { 214 + /// PCI/ISA I/O ports. 215 + pub const IORESOURCE_IO: Flags = Flags::new(bindings::IORESOURCE_IO); 216 + 217 + /// Resource is software muxed. 218 + pub const IORESOURCE_MUXED: Flags = Flags::new(bindings::IORESOURCE_MUXED); 219 + 220 + /// Resource represents a memory region. 221 + pub const IORESOURCE_MEM: Flags = Flags::new(bindings::IORESOURCE_MEM); 222 + 223 + /// Resource represents a memory region that must be ioremaped using `ioremap_np`. 224 + pub const IORESOURCE_MEM_NONPOSTED: Flags = Flags::new(bindings::IORESOURCE_MEM_NONPOSTED); 225 + 226 + const fn new(value: u32) -> Self { 227 + crate::build_assert!(value as u64 <= c_ulong::MAX as u64); 228 + Flags(value as c_ulong) 229 + } 230 + }
+1
rust/kernel/lib.rs
··· 54 54 55 55 pub use ffi; 56 56 57 + pub mod acpi; 57 58 pub mod alloc; 58 59 #[cfg(CONFIG_AUXILIARY_BUS)] 59 60 pub mod auxiliary;
+8 -2
rust/kernel/miscdevice.rs
··· 44 44 /// 45 45 /// # Invariants 46 46 /// 47 - /// `inner` is a registered misc device. 47 + /// - `inner` contains a `struct miscdevice` that is registered using 48 + /// `misc_register()`. 49 + /// - This registration remains valid for the entire lifetime of the 50 + /// [`MiscDeviceRegistration`] instance. 51 + /// - Deregistration occurs exactly once in [`Drop`] via `misc_deregister()`. 52 + /// - `inner` wraps a valid, pinned `miscdevice` created using 53 + /// [`MiscDeviceOptions::into_raw`]. 48 54 #[repr(transparent)] 49 55 #[pin_data(PinnedDrop)] 50 56 pub struct MiscDeviceRegistration<T> { ··· 97 91 // function tells the borrow-checker that the `&Device` reference must not outlive the 98 92 // `&MiscDeviceRegistration<T>` used to obtain it, so the last use of the reference must be 99 93 // before the underlying `struct miscdevice` is destroyed. 100 - unsafe { Device::as_ref((*self.as_raw()).this_device) } 94 + unsafe { Device::from_raw((*self.as_raw()).this_device) } 101 95 } 102 96 } 103 97
+53 -55
rust/kernel/net/phy.rs
··· 6 6 //! 7 7 //! C headers: [`include/linux/phy.h`](srctree/include/linux/phy.h). 8 8 9 - use crate::{error::*, prelude::*, types::Opaque}; 9 + use crate::{device_id::RawDeviceId, error::*, prelude::*, types::Opaque}; 10 10 use core::{marker::PhantomData, ptr::addr_of_mut}; 11 11 12 12 pub mod reg; ··· 285 285 fn as_ref(&self) -> &kernel::device::Device { 286 286 let phydev = self.0.get(); 287 287 // SAFETY: The struct invariant ensures that `mdio.dev` is valid. 288 - unsafe { kernel::device::Device::as_ref(addr_of_mut!((*phydev).mdio.dev)) } 288 + unsafe { kernel::device::Device::from_raw(addr_of_mut!((*phydev).mdio.dev)) } 289 289 } 290 290 } 291 291 ··· 507 507 DriverVTable(Opaque::new(bindings::phy_driver { 508 508 name: T::NAME.as_char_ptr().cast_mut(), 509 509 flags: T::FLAGS, 510 - phy_id: T::PHY_DEVICE_ID.id, 510 + phy_id: T::PHY_DEVICE_ID.id(), 511 511 phy_id_mask: T::PHY_DEVICE_ID.mask_as_int(), 512 512 soft_reset: if T::HAS_SOFT_RESET { 513 513 Some(Adapter::<T>::soft_reset_callback) ··· 691 691 /// 692 692 /// Represents the kernel's `struct mdio_device_id`. This is used to find an appropriate 693 693 /// PHY driver. 694 - pub struct DeviceId { 695 - id: u32, 696 - mask: DeviceMask, 697 - } 694 + #[repr(transparent)] 695 + #[derive(Clone, Copy)] 696 + pub struct DeviceId(bindings::mdio_device_id); 698 697 699 698 impl DeviceId { 700 699 /// Creates a new instance with the exact match mask. 701 700 pub const fn new_with_exact_mask(id: u32) -> Self { 702 - DeviceId { 703 - id, 704 - mask: DeviceMask::Exact, 705 - } 701 + Self(bindings::mdio_device_id { 702 + phy_id: id, 703 + phy_id_mask: DeviceMask::Exact.as_int(), 704 + }) 706 705 } 707 706 708 707 /// Creates a new instance with the model match mask. 709 708 pub const fn new_with_model_mask(id: u32) -> Self { 710 - DeviceId { 711 - id, 712 - mask: DeviceMask::Model, 713 - } 709 + Self(bindings::mdio_device_id { 710 + phy_id: id, 711 + phy_id_mask: DeviceMask::Model.as_int(), 712 + }) 714 713 } 715 714 716 715 /// Creates a new instance with the vendor match mask. 717 716 pub const fn new_with_vendor_mask(id: u32) -> Self { 718 - DeviceId { 719 - id, 720 - mask: DeviceMask::Vendor, 721 - } 717 + Self(bindings::mdio_device_id { 718 + phy_id: id, 719 + phy_id_mask: DeviceMask::Vendor.as_int(), 720 + }) 722 721 } 723 722 724 723 /// Creates a new instance with a custom match mask. 725 724 pub const fn new_with_custom_mask(id: u32, mask: u32) -> Self { 726 - DeviceId { 727 - id, 728 - mask: DeviceMask::Custom(mask), 729 - } 725 + Self(bindings::mdio_device_id { 726 + phy_id: id, 727 + phy_id_mask: DeviceMask::Custom(mask).as_int(), 728 + }) 730 729 } 731 730 732 731 /// Creates a new instance from [`Driver`]. ··· 733 734 T::PHY_DEVICE_ID 734 735 } 735 736 736 - /// Get a `mask` as u32. 737 + /// Get the MDIO device's PHY ID. 738 + pub const fn id(&self) -> u32 { 739 + self.0.phy_id 740 + } 741 + 742 + /// Get the MDIO device's match mask. 737 743 pub const fn mask_as_int(&self) -> u32 { 738 - self.mask.as_int() 744 + self.0.phy_id_mask 739 745 } 740 746 741 747 // macro use only 742 748 #[doc(hidden)] 743 749 pub const fn mdio_device_id(&self) -> bindings::mdio_device_id { 744 - bindings::mdio_device_id { 745 - phy_id: self.id, 746 - phy_id_mask: self.mask.as_int(), 747 - } 750 + self.0 748 751 } 752 + } 753 + 754 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct mdio_device_id` 755 + // and does not add additional invariants, so it's safe to transmute to `RawType`. 756 + unsafe impl RawDeviceId for DeviceId { 757 + type RawType = bindings::mdio_device_id; 749 758 } 750 759 751 760 enum DeviceMask { ··· 856 849 /// } 857 850 /// }; 858 851 /// 859 - /// const _DEVICE_TABLE: [::kernel::bindings::mdio_device_id; 2] = [ 860 - /// ::kernel::bindings::mdio_device_id { 861 - /// phy_id: 0x00000001, 862 - /// phy_id_mask: 0xffffffff, 863 - /// }, 864 - /// ::kernel::bindings::mdio_device_id { 865 - /// phy_id: 0, 866 - /// phy_id_mask: 0, 867 - /// }, 868 - /// ]; 869 - /// #[cfg(MODULE)] 870 - /// #[no_mangle] 871 - /// static __mod_device_table__mdio__phydev: [::kernel::bindings::mdio_device_id; 2] = _DEVICE_TABLE; 852 + /// const N: usize = 1; 853 + /// 854 + /// const TABLE: ::kernel::device_id::IdArray<::kernel::net::phy::DeviceId, (), N> = 855 + /// ::kernel::device_id::IdArray::new_without_index([ 856 + /// ::kernel::net::phy::DeviceId( 857 + /// ::kernel::bindings::mdio_device_id { 858 + /// phy_id: 0x00000001, 859 + /// phy_id_mask: 0xffffffff, 860 + /// }), 861 + /// ]); 862 + /// 863 + /// ::kernel::module_device_table!("mdio", phydev, TABLE); 872 864 /// ``` 873 865 #[macro_export] 874 866 macro_rules! module_phy_driver { ··· 878 872 }; 879 873 880 874 (@device_table [$($dev:expr),+]) => { 881 - // SAFETY: C will not read off the end of this constant since the last element is zero. 882 - const _DEVICE_TABLE: [$crate::bindings::mdio_device_id; 883 - $crate::module_phy_driver!(@count_devices $($dev),+) + 1] = [ 884 - $($dev.mdio_device_id()),+, 885 - $crate::bindings::mdio_device_id { 886 - phy_id: 0, 887 - phy_id_mask: 0 888 - } 889 - ]; 875 + const N: usize = $crate::module_phy_driver!(@count_devices $($dev),+); 890 876 891 - #[cfg(MODULE)] 892 - #[no_mangle] 893 - static __mod_device_table__mdio__phydev: [$crate::bindings::mdio_device_id; 894 - $crate::module_phy_driver!(@count_devices $($dev),+) + 1] = _DEVICE_TABLE; 877 + const TABLE: $crate::device_id::IdArray<$crate::net::phy::DeviceId, (), N> = 878 + $crate::device_id::IdArray::new_without_index([ $(($dev,())),+, ]); 879 + 880 + $crate::module_device_table!("mdio", phydev, TABLE); 895 881 }; 896 882 897 883 (drivers: [$($driver:ident),+ $(,)?], device_table: [$($dev:expr),+ $(,)?], $($f:tt)*) => {
+10 -5
rust/kernel/of.rs
··· 2 2 3 3 //! Device Tree / Open Firmware abstractions. 4 4 5 - use crate::{bindings, device_id::RawDeviceId, prelude::*}; 5 + use crate::{ 6 + bindings, 7 + device_id::{RawDeviceId, RawDeviceIdIndex}, 8 + prelude::*, 9 + }; 6 10 7 11 /// IdTable type for OF drivers. 8 12 pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; ··· 16 12 #[derive(Clone, Copy)] 17 13 pub struct DeviceId(bindings::of_device_id); 18 14 19 - // SAFETY: 20 - // * `DeviceId` is a `#[repr(transparent)` wrapper of `struct of_device_id` and does not add 21 - // additional invariants, so it's safe to transmute to `RawType`. 22 - // * `DRIVER_DATA_OFFSET` is the offset to the `data` field. 15 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct of_device_id` and 16 + // does not add additional invariants, so it's safe to transmute to `RawType`. 23 17 unsafe impl RawDeviceId for DeviceId { 24 18 type RawType = bindings::of_device_id; 19 + } 25 20 21 + // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `data` field. 22 + unsafe impl RawDeviceIdIndex for DeviceId { 26 23 const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::of_device_id, data); 27 24 28 25 fn index(&self) -> usize {
+52 -35
rust/kernel/pci.rs
··· 5 5 //! C header: [`include/linux/pci.h`](srctree/include/linux/pci.h) 6 6 7 7 use crate::{ 8 - alloc::flags::*, 9 8 bindings, container_of, device, 10 - device_id::RawDeviceId, 9 + device_id::{RawDeviceId, RawDeviceIdIndex}, 11 10 devres::Devres, 12 11 driver, 13 - error::{to_result, Result}, 12 + error::{from_result, to_result, Result}, 14 13 io::Io, 15 14 io::IoRaw, 16 15 str::CStr, 17 - types::{ARef, ForeignOwnable, Opaque}, 16 + types::{ARef, Opaque}, 18 17 ThisModule, 19 18 }; 20 19 use core::{ ··· 65 66 // `struct pci_dev`. 66 67 // 67 68 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`. 68 - let pdev = unsafe { &*pdev.cast::<Device<device::Core>>() }; 69 + let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() }; 69 70 70 - // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct pci_device_id` and 71 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct pci_device_id` and 71 72 // does not add additional invariants, so it's safe to transmute. 72 73 let id = unsafe { &*id.cast::<DeviceId>() }; 73 74 let info = T::ID_TABLE.info(id.index()); 74 75 75 - match T::probe(pdev, info) { 76 - Ok(data) => { 77 - // Let the `struct pci_dev` own a reference of the driver's private data. 78 - // SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a 79 - // `struct pci_dev`. 80 - unsafe { bindings::pci_set_drvdata(pdev.as_raw(), data.into_foreign() as _) }; 81 - } 82 - Err(err) => return Error::to_errno(err), 83 - } 76 + from_result(|| { 77 + let data = T::probe(pdev, info)?; 84 78 85 - 0 79 + pdev.as_ref().set_drvdata(data); 80 + Ok(0) 81 + }) 86 82 } 87 83 88 84 extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) { 89 85 // SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a 90 86 // `struct pci_dev`. 91 - let ptr = unsafe { bindings::pci_get_drvdata(pdev) }.cast(); 87 + // 88 + // INVARIANT: `pdev` is valid for the duration of `remove_callback()`. 89 + let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() }; 92 90 93 91 // SAFETY: `remove_callback` is only ever called after a successful call to 94 - // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized 95 - // `KBox<T>` pointer created through `KBox::into_foreign`. 96 - let _ = unsafe { KBox::<T>::from_foreign(ptr) }; 92 + // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 93 + // and stored a `Pin<KBox<T>>`. 94 + let data = unsafe { pdev.as_ref().drvdata_obtain::<Pin<KBox<T>>>() }; 95 + 96 + T::unbind(pdev, data.as_ref()); 97 97 } 98 98 } 99 99 ··· 159 161 } 160 162 } 161 163 162 - // SAFETY: 163 - // * `DeviceId` is a `#[repr(transparent)` wrapper of `pci_device_id` and does not add 164 - // additional invariants, so it's safe to transmute to `RawType`. 165 - // * `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 164 + // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `pci_device_id` and does not add 165 + // additional invariants, so it's safe to transmute to `RawType`. 166 166 unsafe impl RawDeviceId for DeviceId { 167 167 type RawType = bindings::pci_device_id; 168 + } 168 169 170 + // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 171 + unsafe impl RawDeviceIdIndex for DeviceId { 169 172 const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data); 170 173 171 174 fn index(&self) -> usize { ··· 240 241 /// Called when a new platform device is added or discovered. 241 242 /// Implementers should attempt to initialize the device here. 242 243 fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 244 + 245 + /// Platform driver unbind. 246 + /// 247 + /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback 248 + /// is optional. 249 + /// 250 + /// This callback serves as a place for drivers to perform teardown operations that require a 251 + /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O 252 + /// operations to gracefully tear down the device. 253 + /// 254 + /// Otherwise, release operations for driver resources should be performed in `Self::drop`. 255 + fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) { 256 + let _ = (dev, this); 257 + } 243 258 } 244 259 245 260 /// The PCI device representation. ··· 264 251 /// 265 252 /// # Invariants 266 253 /// 267 - /// A [`Device`] instance represents a valid `struct device` created by the C portion of the kernel. 254 + /// A [`Device`] instance represents a valid `struct pci_dev` created by the C portion of the 255 + /// kernel. 268 256 #[repr(transparent)] 269 257 pub struct Device<Ctx: device::DeviceContext = device::Normal>( 270 258 Opaque<bindings::pci_dev>, ··· 412 398 impl Device<device::Bound> { 413 399 /// Mapps an entire PCI-BAR after performing a region-request on it. I/O operation bound checks 414 400 /// can be performed on compile time for offsets (plus the requested type size) < SIZE. 415 - pub fn iomap_region_sized<const SIZE: usize>( 416 - &self, 401 + pub fn iomap_region_sized<'a, const SIZE: usize>( 402 + &'a self, 417 403 bar: u32, 418 - name: &CStr, 419 - ) -> Result<Devres<Bar<SIZE>>> { 420 - let bar = Bar::<SIZE>::new(self, bar, name)?; 421 - let devres = Devres::new(self.as_ref(), bar, GFP_KERNEL)?; 422 - 423 - Ok(devres) 404 + name: &'a CStr, 405 + ) -> impl PinInit<Devres<Bar<SIZE>>, Error> + 'a { 406 + Devres::new(self.as_ref(), Bar::<SIZE>::new(self, bar, name)) 424 407 } 425 408 426 409 /// Mapps an entire PCI-BAR after performing a region-request on it. 427 - pub fn iomap_region(&self, bar: u32, name: &CStr) -> Result<Devres<Bar>> { 410 + pub fn iomap_region<'a>( 411 + &'a self, 412 + bar: u32, 413 + name: &'a CStr, 414 + ) -> impl PinInit<Devres<Bar>, Error> + 'a { 428 415 self.iomap_region_sized::<0>(bar, name) 429 416 } 430 417 } ··· 449 434 kernel::impl_device_context_deref!(unsafe { Device }); 450 435 kernel::impl_device_context_into_aref!(Device); 451 436 437 + impl crate::dma::Device for Device<device::Core> {} 438 + 452 439 // SAFETY: Instances of `Device` are always reference-counted. 453 440 unsafe impl crate::types::AlwaysRefCounted for Device { 454 441 fn inc_ref(&self) { ··· 471 454 let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) }; 472 455 473 456 // SAFETY: `dev` points to a valid `struct device`. 474 - unsafe { device::Device::as_ref(dev) } 457 + unsafe { device::Device::from_raw(dev) } 475 458 } 476 459 } 477 460
+120 -24
rust/kernel/platform.rs
··· 5 5 //! C header: [`include/linux/platform_device.h`](srctree/include/linux/platform_device.h) 6 6 7 7 use crate::{ 8 - bindings, container_of, device, driver, 9 - error::{to_result, Result}, 8 + acpi, bindings, container_of, 9 + device::{self, Bound}, 10 + driver, 11 + error::{from_result, to_result, Result}, 12 + io::{mem::IoRequest, Resource}, 10 13 of, 11 14 prelude::*, 12 - str::CStr, 13 - types::{ForeignOwnable, Opaque}, 15 + types::Opaque, 14 16 ThisModule, 15 17 }; 16 18 ··· 39 37 None => core::ptr::null(), 40 38 }; 41 39 40 + let acpi_table = match T::ACPI_ID_TABLE { 41 + Some(table) => table.as_ptr(), 42 + None => core::ptr::null(), 43 + }; 44 + 42 45 // SAFETY: It's safe to set the fields of `struct platform_driver` on initialization. 43 46 unsafe { 44 47 (*pdrv.get()).driver.name = name.as_char_ptr(); 45 48 (*pdrv.get()).probe = Some(Self::probe_callback); 46 49 (*pdrv.get()).remove = Some(Self::remove_callback); 47 50 (*pdrv.get()).driver.of_match_table = of_table; 51 + (*pdrv.get()).driver.acpi_match_table = acpi_table; 48 52 } 49 53 50 54 // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. ··· 69 61 // `struct platform_device`. 70 62 // 71 63 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`. 72 - let pdev = unsafe { &*pdev.cast::<Device<device::Core>>() }; 73 - 64 + let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() }; 74 65 let info = <Self as driver::Adapter>::id_info(pdev.as_ref()); 75 - match T::probe(pdev, info) { 76 - Ok(data) => { 77 - // Let the `struct platform_device` own a reference of the driver's private data. 78 - // SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a 79 - // `struct platform_device`. 80 - unsafe { bindings::platform_set_drvdata(pdev.as_raw(), data.into_foreign() as _) }; 81 - } 82 - Err(err) => return Error::to_errno(err), 83 - } 84 66 85 - 0 67 + from_result(|| { 68 + let data = T::probe(pdev, info)?; 69 + 70 + pdev.as_ref().set_drvdata(data); 71 + Ok(0) 72 + }) 86 73 } 87 74 88 75 extern "C" fn remove_callback(pdev: *mut bindings::platform_device) { 89 - // SAFETY: `pdev` is a valid pointer to a `struct platform_device`. 90 - let ptr = unsafe { bindings::platform_get_drvdata(pdev) }.cast(); 76 + // SAFETY: The platform bus only ever calls the remove callback with a valid pointer to a 77 + // `struct platform_device`. 78 + // 79 + // INVARIANT: `pdev` is valid for the duration of `probe_callback()`. 80 + let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() }; 91 81 92 82 // SAFETY: `remove_callback` is only ever called after a successful call to 93 - // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized 94 - // `KBox<T>` pointer created through `KBox::into_foreign`. 95 - let _ = unsafe { KBox::<T>::from_foreign(ptr) }; 83 + // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 84 + // and stored a `Pin<KBox<T>>`. 85 + let data = unsafe { pdev.as_ref().drvdata_obtain::<Pin<KBox<T>>>() }; 86 + 87 + T::unbind(pdev, data.as_ref()); 96 88 } 97 89 } 98 90 ··· 101 93 102 94 fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> { 103 95 T::OF_ID_TABLE 96 + } 97 + 98 + fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>> { 99 + T::ACPI_ID_TABLE 104 100 } 105 101 } 106 102 ··· 135 123 /// # Example 136 124 /// 137 125 ///``` 138 - /// # use kernel::{bindings, c_str, device::Core, of, platform}; 126 + /// # use kernel::{acpi, bindings, c_str, device::Core, of, platform}; 139 127 /// 140 128 /// struct MyDriver; 141 129 /// ··· 148 136 /// ] 149 137 /// ); 150 138 /// 139 + /// kernel::acpi_device_table!( 140 + /// ACPI_TABLE, 141 + /// MODULE_ACPI_TABLE, 142 + /// <MyDriver as platform::Driver>::IdInfo, 143 + /// [ 144 + /// (acpi::DeviceId::new(c_str!("LNUXBEEF")), ()) 145 + /// ] 146 + /// ); 147 + /// 151 148 /// impl platform::Driver for MyDriver { 152 149 /// type IdInfo = (); 153 150 /// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); 151 + /// const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); 154 152 /// 155 153 /// fn probe( 156 154 /// _pdev: &platform::Device<Core>, ··· 180 158 type IdInfo: 'static; 181 159 182 160 /// The table of OF device ids supported by the driver. 183 - const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>>; 161 + const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None; 162 + 163 + /// The table of ACPI device ids supported by the driver. 164 + const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = None; 184 165 185 166 /// Platform driver probe. 186 167 /// ··· 191 166 /// Implementers should attempt to initialize the device here. 192 167 fn probe(dev: &Device<device::Core>, id_info: Option<&Self::IdInfo>) 193 168 -> Result<Pin<KBox<Self>>>; 169 + 170 + /// Platform driver unbind. 171 + /// 172 + /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback 173 + /// is optional. 174 + /// 175 + /// This callback serves as a place for drivers to perform teardown operations that require a 176 + /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O 177 + /// operations to gracefully tear down the device. 178 + /// 179 + /// Otherwise, release operations for driver resources should be performed in `Self::drop`. 180 + fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) { 181 + let _ = (dev, this); 182 + } 194 183 } 195 184 196 185 /// The platform device representation. ··· 227 188 fn as_raw(&self) -> *mut bindings::platform_device { 228 189 self.0.get() 229 190 } 191 + 192 + /// Returns the resource at `index`, if any. 193 + pub fn resource_by_index(&self, index: u32) -> Option<&Resource> { 194 + // SAFETY: `self.as_raw()` returns a valid pointer to a `struct platform_device`. 195 + let resource = unsafe { 196 + bindings::platform_get_resource(self.as_raw(), bindings::IORESOURCE_MEM, index) 197 + }; 198 + 199 + if resource.is_null() { 200 + return None; 201 + } 202 + 203 + // SAFETY: `resource` is a valid pointer to a `struct resource` as 204 + // returned by `platform_get_resource`. 205 + Some(unsafe { Resource::from_raw(resource) }) 206 + } 207 + 208 + /// Returns the resource with a given `name`, if any. 209 + pub fn resource_by_name(&self, name: &CStr) -> Option<&Resource> { 210 + // SAFETY: `self.as_raw()` returns a valid pointer to a `struct 211 + // platform_device` and `name` points to a valid C string. 212 + let resource = unsafe { 213 + bindings::platform_get_resource_byname( 214 + self.as_raw(), 215 + bindings::IORESOURCE_MEM, 216 + name.as_char_ptr(), 217 + ) 218 + }; 219 + 220 + if resource.is_null() { 221 + return None; 222 + } 223 + 224 + // SAFETY: `resource` is a valid pointer to a `struct resource` as 225 + // returned by `platform_get_resource`. 226 + Some(unsafe { Resource::from_raw(resource) }) 227 + } 228 + } 229 + 230 + impl Device<Bound> { 231 + /// Returns an `IoRequest` for the resource at `index`, if any. 232 + pub fn io_request_by_index(&self, index: u32) -> Option<IoRequest<'_>> { 233 + self.resource_by_index(index) 234 + // SAFETY: `resource` is a valid resource for `&self` during the 235 + // lifetime of the `IoRequest`. 236 + .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) }) 237 + } 238 + 239 + /// Returns an `IoRequest` for the resource with a given `name`, if any. 240 + pub fn io_request_by_name(&self, name: &CStr) -> Option<IoRequest<'_>> { 241 + self.resource_by_name(name) 242 + // SAFETY: `resource` is a valid resource for `&self` during the 243 + // lifetime of the `IoRequest`. 244 + .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) }) 245 + } 230 246 } 231 247 232 248 // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic 233 249 // argument. 234 250 kernel::impl_device_context_deref!(unsafe { Device }); 235 251 kernel::impl_device_context_into_aref!(Device); 252 + 253 + impl crate::dma::Device for Device<device::Core> {} 236 254 237 255 // SAFETY: Instances of `Device` are always reference-counted. 238 256 unsafe impl crate::types::AlwaysRefCounted for Device { ··· 311 215 let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) }; 312 216 313 217 // SAFETY: `dev` points to a valid `struct device`. 314 - unsafe { device::Device::as_ref(dev) } 218 + unsafe { device::Device::from_raw(dev) } 315 219 } 316 220 } 317 221
+5 -3
rust/kernel/revocable.rs
··· 5 5 //! The [`Revocable`] type wraps other types and allows access to them to be revoked. The existence 6 6 //! of a [`RevocableGuard`] ensures that objects remain valid. 7 7 8 + use pin_init::Wrapper; 9 + 8 10 use crate::{bindings, prelude::*, sync::rcu, types::Opaque}; 9 11 use core::{ 10 12 marker::PhantomData, ··· 82 80 83 81 impl<T> Revocable<T> { 84 82 /// Creates a new revocable instance of the given data. 85 - pub fn new(data: impl PinInit<T>) -> impl PinInit<Self> { 86 - pin_init!(Self { 83 + pub fn new<E>(data: impl PinInit<T, E>) -> impl PinInit<Self, E> { 84 + try_pin_init!(Self { 87 85 is_available: AtomicBool::new(true), 88 86 data <- Opaque::pin_init(data), 89 - }) 87 + }? E) 90 88 } 91 89 92 90 /// Tries to access the revocable wrapped object.
+14 -12
rust/kernel/types.rs
··· 9 9 ops::{Deref, DerefMut}, 10 10 ptr::NonNull, 11 11 }; 12 - use pin_init::{PinInit, Zeroable}; 12 + use pin_init::{PinInit, Wrapper, Zeroable}; 13 13 14 14 /// Used to transfer ownership to and from foreign (non-Rust) languages. 15 15 /// ··· 353 353 } 354 354 } 355 355 356 - /// Create an opaque pin-initializer from the given pin-initializer. 357 - pub fn pin_init(slot: impl PinInit<T>) -> impl PinInit<Self> { 358 - Self::ffi_init(|ptr: *mut T| { 359 - // SAFETY: 360 - // - `ptr` is a valid pointer to uninitialized memory, 361 - // - `slot` is not accessed on error; the call is infallible, 362 - // - `slot` is pinned in memory. 363 - let _ = unsafe { PinInit::<T>::__pinned_init(slot, ptr) }; 364 - }) 365 - } 366 - 367 356 /// Creates a pin-initializer from the given initializer closure. 368 357 /// 369 358 /// The returned initializer calls the given closure with the pointer to the inner `T` of this ··· 401 412 /// references. 402 413 pub const fn raw_get(this: *const Self) -> *mut T { 403 414 UnsafeCell::raw_get(this.cast::<UnsafeCell<MaybeUninit<T>>>()).cast::<T>() 415 + } 416 + } 417 + 418 + impl<T> Wrapper<T> for Opaque<T> { 419 + /// Create an opaque pin-initializer from the given pin-initializer. 420 + fn pin_init<E>(slot: impl PinInit<T, E>) -> impl PinInit<Self, E> { 421 + Self::try_ffi_init(|ptr: *mut T| { 422 + // SAFETY: 423 + // - `ptr` is a valid pointer to uninitialized memory, 424 + // - `slot` is not accessed on error, 425 + // - `slot` is pinned in memory. 426 + unsafe { PinInit::<T, E>::__pinned_init(slot, ptr) } 427 + }) 404 428 } 405 429 } 406 430
+32 -8
rust/pin-init/src/lib.rs
··· 1390 1390 unsafe { pin_init_from_closure(init) } 1391 1391 } 1392 1392 1393 - // SAFETY: Every type can be initialized by-value. 1394 - unsafe impl<T, E> Init<T, E> for T { 1395 - unsafe fn __init(self, slot: *mut T) -> Result<(), E> { 1396 - // SAFETY: TODO. 1393 + // SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`. 1394 + unsafe impl<T> Init<T> for T { 1395 + unsafe fn __init(self, slot: *mut T) -> Result<(), Infallible> { 1396 + // SAFETY: `slot` is valid for writes by the safety requirements of this function. 1397 1397 unsafe { slot.write(self) }; 1398 1398 Ok(()) 1399 1399 } 1400 1400 } 1401 1401 1402 - // SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`. 1403 - unsafe impl<T, E> PinInit<T, E> for T { 1402 + // SAFETY: the `__pinned_init` function always returns `Ok(())` and initializes every field of 1403 + // `slot`. Additionally, all pinning invariants of `T` are upheld. 1404 + unsafe impl<T> PinInit<T> for T { 1405 + unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible> { 1406 + // SAFETY: `slot` is valid for writes by the safety requirements of this function. 1407 + unsafe { slot.write(self) }; 1408 + Ok(()) 1409 + } 1410 + } 1411 + 1412 + // SAFETY: when the `__init` function returns with 1413 + // - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld. 1414 + // - `Err(err)`, slot was not written to. 1415 + unsafe impl<T, E> Init<T, E> for Result<T, E> { 1416 + unsafe fn __init(self, slot: *mut T) -> Result<(), E> { 1417 + // SAFETY: `slot` is valid for writes by the safety requirements of this function. 1418 + unsafe { slot.write(self?) }; 1419 + Ok(()) 1420 + } 1421 + } 1422 + 1423 + // SAFETY: when the `__pinned_init` function returns with 1424 + // - `Ok(())`, `slot` was initialized and all pinned invariants of `T` are upheld. 1425 + // - `Err(err)`, slot was not written to. 1426 + unsafe impl<T, E> PinInit<T, E> for Result<T, E> { 1404 1427 unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { 1405 - // SAFETY: TODO. 1406 - unsafe { self.__init(slot) } 1428 + // SAFETY: `slot` is valid for writes by the safety requirements of this function. 1429 + unsafe { slot.write(self?) }; 1430 + Ok(()) 1407 1431 } 1408 1432 } 1409 1433
+2 -2
samples/kobject/kobject-example.c
··· 13 13 14 14 /* 15 15 * This module shows how to create a simple subdirectory in sysfs called 16 - * /sys/kernel/kobject-example In that directory, 3 files are created: 16 + * /sys/kernel/kobject_example In that directory, 3 files are created: 17 17 * "foo", "baz", and "bar". If an integer is written to these files, it can be 18 18 * later read out of it. 19 19 */ ··· 102 102 * created for the attributes with the directory being the name of the 103 103 * attribute group. 104 104 */ 105 - static struct attribute_group attr_group = { 105 + static const struct attribute_group attr_group = { 106 106 .attrs = attrs, 107 107 }; 108 108
+2 -2
samples/kobject/kset-example.c
··· 14 14 15 15 /* 16 16 * This module shows how to create a kset in sysfs called 17 - * /sys/kernel/kset-example 18 - * Then tree kobjects are created and assigned to this kset, "foo", "baz", 17 + * /sys/kernel/kset_example 18 + * Then three kobjects are created and assigned to this kset, "foo", "baz", 19 19 * and "bar". In those kobjects, attributes of the same name are also 20 20 * created and if an integer is written to these files, it can be later 21 21 * read out of it.
+13 -1
samples/rust/rust_dma.rs
··· 4 4 //! 5 5 //! To make this driver probe, QEMU must be run with `-device pci-testdev`. 6 6 7 - use kernel::{bindings, device::Core, dma::CoherentAllocation, pci, prelude::*, types::ARef}; 7 + use kernel::{ 8 + bindings, 9 + device::Core, 10 + dma::{CoherentAllocation, Device, DmaMask}, 11 + pci, 12 + prelude::*, 13 + types::ARef, 14 + }; 8 15 9 16 struct DmaSampleDriver { 10 17 pdev: ARef<pci::Device>, ··· 57 50 58 51 fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> { 59 52 dev_info!(pdev.as_ref(), "Probe DMA test driver.\n"); 53 + 54 + let mask = DmaMask::new::<64>(); 55 + 56 + // SAFETY: There are no concurrent calls to DMA allocation and mapping primitives. 57 + unsafe { pdev.dma_set_mask_and_coherent(mask)? }; 60 58 61 59 let ca: CoherentAllocation<MyStruct> = 62 60 CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?;
+1 -2
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, bindings, c_str, device::Core, driver, error::Error, pci, prelude::*, str::CStr, 9 - InPlaceModule, 8 + auxiliary, bindings, c_str, device::Core, driver, error::Error, pci, prelude::*, InPlaceModule, 10 9 }; 11 10 12 11 use pin_init::PinInit;
+20 -10
samples/rust/rust_driver_pci.rs
··· 18 18 19 19 type Bar0 = pci::Bar<{ Regs::END }>; 20 20 21 - #[derive(Debug)] 21 + #[derive(Copy, Clone, Debug)] 22 22 struct TestIndex(u8); 23 23 24 24 impl TestIndex { 25 25 const NO_EVENTFD: Self = Self(0); 26 26 } 27 27 28 + #[pin_data(PinnedDrop)] 28 29 struct SampleDriver { 29 30 pdev: ARef<pci::Device>, 31 + #[pin] 30 32 bar: Devres<Bar0>, 33 + index: TestIndex, 31 34 } 32 35 33 36 kernel::pci_device_table!( ··· 76 73 pdev.enable_device_mem()?; 77 74 pdev.set_master(); 78 75 79 - let bar = pdev.iomap_region_sized::<{ Regs::END }>(0, c_str!("rust_driver_pci"))?; 80 - 81 - let drvdata = KBox::new( 82 - Self { 76 + let drvdata = KBox::pin_init( 77 + try_pin_init!(Self { 83 78 pdev: pdev.into(), 84 - bar, 85 - }, 79 + bar <- pdev.iomap_region_sized::<{ Regs::END }>(0, c_str!("rust_driver_pci")), 80 + index: *info, 81 + }), 86 82 GFP_KERNEL, 87 83 )?; 88 84 ··· 92 90 Self::testdev(info, bar)? 93 91 ); 94 92 95 - Ok(drvdata.into()) 93 + Ok(drvdata) 94 + } 95 + 96 + fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) { 97 + if let Ok(bar) = this.bar.access(pdev.as_ref()) { 98 + // Reset pci-testdev by writing a new test index. 99 + bar.write8(this.index.0, Regs::TEST); 100 + } 96 101 } 97 102 } 98 103 99 - impl Drop for SampleDriver { 100 - fn drop(&mut self) { 104 + #[pinned_drop] 105 + impl PinnedDrop for SampleDriver { 106 + fn drop(self: Pin<&mut Self>) { 101 107 dev_dbg!(self.pdev.as_ref(), "Remove Rust PCI driver sample.\n"); 102 108 } 103 109 }
+144 -3
samples/rust/rust_driver_platform.rs
··· 2 2 3 3 //! Rust Platform driver sample. 4 4 5 - use kernel::{c_str, device::Core, of, platform, prelude::*, types::ARef}; 5 + //! ACPI match table test 6 + //! 7 + //! This demonstrates how to test an ACPI-based Rust platform driver using QEMU 8 + //! with a custom SSDT. 9 + //! 10 + //! Steps: 11 + //! 12 + //! 1. **Create an SSDT source file** (`ssdt.dsl`) with the following content: 13 + //! 14 + //! ```asl 15 + //! DefinitionBlock ("", "SSDT", 2, "TEST", "VIRTACPI", 0x00000001) 16 + //! { 17 + //! Scope (\_SB) 18 + //! { 19 + //! Device (T432) 20 + //! { 21 + //! Name (_HID, "LNUXBEEF") // ACPI hardware ID to match 22 + //! Name (_UID, 1) 23 + //! Name (_STA, 0x0F) // Device present, enabled 24 + //! Name (_CRS, ResourceTemplate () 25 + //! { 26 + //! Memory32Fixed (ReadWrite, 0xFED00000, 0x1000) 27 + //! }) 28 + //! } 29 + //! } 30 + //! } 31 + //! ``` 32 + //! 33 + //! 2. **Compile the table**: 34 + //! 35 + //! ```sh 36 + //! iasl -tc ssdt.dsl 37 + //! ``` 38 + //! 39 + //! This generates `ssdt.aml` 40 + //! 41 + //! 3. **Run QEMU** with the compiled AML file: 42 + //! 43 + //! ```sh 44 + //! qemu-system-x86_64 -m 512M \ 45 + //! -enable-kvm \ 46 + //! -kernel path/to/bzImage \ 47 + //! -append "root=/dev/sda console=ttyS0" \ 48 + //! -hda rootfs.img \ 49 + //! -serial stdio \ 50 + //! -acpitable file=ssdt.aml 51 + //! ``` 52 + //! 53 + //! Requirements: 54 + //! - The `rust_driver_platform` must be present either: 55 + //! - built directly into the kernel (`bzImage`), or 56 + //! - available as a `.ko` file and loadable from `rootfs.img` 57 + //! 58 + //! 4. **Verify it worked** by checking `dmesg`: 59 + //! 60 + //! ``` 61 + //! rust_driver_platform LNUXBEEF:00: Probed with info: '0'. 62 + //! ``` 63 + //! 64 + 65 + use kernel::{ 66 + acpi, c_str, 67 + device::{ 68 + self, 69 + property::{FwNodeReferenceArgs, NArgs}, 70 + Core, 71 + }, 72 + of, platform, 73 + prelude::*, 74 + str::CString, 75 + types::ARef, 76 + }; 6 77 7 78 struct SampleDriver { 8 79 pdev: ARef<platform::Device>, ··· 88 17 [(of::DeviceId::new(c_str!("test,rust-device")), Info(42))] 89 18 ); 90 19 20 + kernel::acpi_device_table!( 21 + ACPI_TABLE, 22 + MODULE_ACPI_TABLE, 23 + <SampleDriver as platform::Driver>::IdInfo, 24 + [(acpi::DeviceId::new(c_str!("LNUXBEEF")), Info(0))] 25 + ); 26 + 91 27 impl platform::Driver for SampleDriver { 92 28 type IdInfo = Info; 93 29 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE); 30 + const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); 94 31 95 32 fn probe( 96 33 pdev: &platform::Device<Core>, 97 34 info: Option<&Self::IdInfo>, 98 35 ) -> Result<Pin<KBox<Self>>> { 99 - dev_dbg!(pdev.as_ref(), "Probe Rust Platform driver sample.\n"); 36 + let dev = pdev.as_ref(); 37 + 38 + dev_dbg!(dev, "Probe Rust Platform driver sample.\n"); 100 39 101 40 if let Some(info) = info { 102 - dev_info!(pdev.as_ref(), "Probed with info: '{}'.\n", info.0); 41 + dev_info!(dev, "Probed with info: '{}'.\n", info.0); 42 + } 43 + 44 + if dev.fwnode().is_some_and(|node| node.is_of_node()) { 45 + Self::properties_parse(dev)?; 103 46 } 104 47 105 48 let drvdata = KBox::new(Self { pdev: pdev.into() }, GFP_KERNEL)?; 106 49 107 50 Ok(drvdata.into()) 51 + } 52 + } 53 + 54 + impl SampleDriver { 55 + fn properties_parse(dev: &device::Device) -> Result { 56 + let fwnode = dev.fwnode().ok_or(ENOENT)?; 57 + 58 + if let Ok(idx) = 59 + fwnode.property_match_string(c_str!("compatible"), c_str!("test,rust-device")) 60 + { 61 + dev_info!(dev, "matched compatible string idx = {}\n", idx); 62 + } 63 + 64 + let name = c_str!("compatible"); 65 + let prop = fwnode.property_read::<CString>(name).required_by(dev)?; 66 + dev_info!(dev, "'{name}'='{prop:?}'\n"); 67 + 68 + let name = c_str!("test,bool-prop"); 69 + let prop = fwnode.property_read_bool(c_str!("test,bool-prop")); 70 + dev_info!(dev, "'{name}'='{prop}'\n"); 71 + 72 + if fwnode.property_present(c_str!("test,u32-prop")) { 73 + dev_info!(dev, "'test,u32-prop' is present\n"); 74 + } 75 + 76 + let name = c_str!("test,u32-optional-prop"); 77 + let prop = fwnode.property_read::<u32>(name).or(0x12); 78 + dev_info!(dev, "'{name}'='{prop:#x}' (default = 0x12)\n",); 79 + 80 + // A missing required property will print an error. Discard the error to 81 + // prevent properties_parse from failing in that case. 82 + let name = c_str!("test,u32-required-prop"); 83 + let _ = fwnode.property_read::<u32>(name).required_by(dev); 84 + 85 + let name = c_str!("test,u32-prop"); 86 + let prop: u32 = fwnode.property_read(name).required_by(dev)?; 87 + dev_info!(dev, "'{name}'='{prop:#x}'\n"); 88 + 89 + let name = c_str!("test,i16-array"); 90 + let prop: [i16; 4] = fwnode.property_read(name).required_by(dev)?; 91 + dev_info!(dev, "'{name}'='{prop:?}'\n"); 92 + let len = fwnode.property_count_elem::<u16>(name)?; 93 + dev_info!(dev, "'{name}' length is {len}\n",); 94 + 95 + let name = c_str!("test,i16-array"); 96 + let prop: KVec<i16> = fwnode.property_read_array_vec(name, 4)?.required_by(dev)?; 97 + dev_info!(dev, "'{name}'='{prop:?}' (KVec)\n"); 98 + 99 + for child in fwnode.children() { 100 + let name = c_str!("test,ref-arg"); 101 + let nargs = NArgs::N(2); 102 + let prop: FwNodeReferenceArgs = child.property_get_reference_args(name, nargs, 0)?; 103 + dev_info!(dev, "'{name}'='{prop:?}'\n"); 104 + } 105 + 106 + Ok(()) 108 107 } 109 108 } 110 109
+1
scripts/const_structs.checkpatch
··· 1 1 acpi_dock_ops 2 2 address_space_operations 3 3 backlight_ops 4 + bin_attribute 4 5 block_device_operations 5 6 bus_type 6 7 clk_ops