mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'driver-core-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core
Pull driver core updates from Danilo Krummrich:
"Auxiliary:
- Drop call to dev_pm_domain_detach() in auxiliary_bus_probe()
- Optimize logic of auxiliary_match_id()
Rust:
- Auxiliary:
- Use primitive C types from prelude
- DebugFs:
- Add debugfs support for simple read/write files and custom
callbacks through a File-type-based and directory-scope-based
API
- Sample driver code for the File-type-based API
- Sample module code for the directory-scope-based API
- I/O:
- Add io::poll module and implement Rust specific
read_poll_timeout() helper
- IRQ:
- Implement support for threaded and non-threaded device IRQs
based on (&Device<Bound>, IRQ number) tuples (IrqRequest)
- Provide &Device<Bound> cookie in IRQ handlers
- PCI:
- Support IRQ requests from IRQ vectors for a specific
pci::Device<Bound>
- Implement accessors for subsystem IDs, revision, devid and
resource start
- Provide dedicated pci::Vendor and pci::Class types for vendor
and class ID numbers
- Implement Display to print actual vendor and class names; Debug
to print the raw ID numbers
- Add pci::DeviceId::from_class_and_vendor() helper
- Use primitive C types from prelude
- Various minor inline and (safety) comment improvements
- Platform:
- Support IRQ requests from IRQ vectors for a specific
platform::Device<Bound>
- Nova:
- Use pci::DeviceId::from_class_and_vendor() to avoid probing
non-display/compute PCI functions
- Misc:
- Add helper for cpu_relax()
- Update ARef import from sync::aref
sysfs:
- Remove bin_attrs_new field from struct attribute_group
- Remove read_new() and write_new() from struct bin_attribute
Misc:
- Document potential race condition in get_dev_from_fwnode()
- Constify node_group argument in software node registration
functions
- Fix order of kernel-doc parameters in various functions
- Set power.no_pm flag for faux devices
- Set power.no_callbacks flag along with the power.no_pm flag
- Constify the pmu_bus bus type
- Minor spelling fixes"
* tag 'driver-core-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: (43 commits)
rust: pci: display symbolic PCI vendor names
rust: pci: display symbolic PCI class names
rust: pci: fix incorrect platform reference in PCI driver probe doc comment
rust: pci: fix incorrect platform reference in PCI driver unbind doc comment
perf: make pmu_bus const
samples: rust: Add scoped debugfs sample driver
rust: debugfs: Add support for scoped directories
samples: rust: Add debugfs sample driver
rust: debugfs: Add support for callback-based files
rust: debugfs: Add support for writable files
rust: debugfs: Add support for read-only files
rust: debugfs: Add initial support for directories
driver core: auxiliary bus: Optimize logic of auxiliary_match_id()
driver core: auxiliary bus: Drop dev_pm_domain_detach() call
driver core: Fix order of the kernel-doc parameters
driver core: get_dev_from_fwnode(): document potential race
drivers: base: fix "publically"->"publicly"
driver core/PM: Set power.no_callbacks along with power.no_pm
driver core: faux: Set power.no_pm for faux devices
rust: pci: inline several tiny functions
...
This commit is contained in:
+20
@@ -7021,6 +7021,21 @@ F: drivers/devfreq/event/
|
||||
F: include/dt-bindings/pmu/exynos_ppmu.h
|
||||
F: include/linux/devfreq-event.h
|
||||
|
||||
DEVICE I/O & IRQ [RUST]
|
||||
M: Danilo Krummrich <dakr@kernel.org>
|
||||
M: Alice Ryhl <aliceryhl@google.com>
|
||||
M: Daniel Almeida <daniel.almeida@collabora.com>
|
||||
L: rust-for-linux@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://rust-for-linux.com
|
||||
B: https://github.com/Rust-for-Linux/linux/issues
|
||||
C: https://rust-for-linux.zulipchat.com
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
|
||||
F: rust/kernel/io.rs
|
||||
F: rust/kernel/io/
|
||||
F: rust/kernel/irq.rs
|
||||
F: rust/kernel/irq/
|
||||
|
||||
DEVICE RESOURCE MANAGEMENT HELPERS
|
||||
M: Hans de Goede <hansg@kernel.org>
|
||||
R: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
@@ -7472,6 +7487,8 @@ F: include/linux/kobj*
|
||||
F: include/linux/property.h
|
||||
F: include/linux/sysfs.h
|
||||
F: lib/kobj*
|
||||
F: rust/kernel/debugfs.rs
|
||||
F: rust/kernel/debugfs/
|
||||
F: rust/kernel/device.rs
|
||||
F: rust/kernel/device/
|
||||
F: rust/kernel/device_id.rs
|
||||
@@ -7479,6 +7496,8 @@ F: rust/kernel/devres.rs
|
||||
F: rust/kernel/driver.rs
|
||||
F: rust/kernel/faux.rs
|
||||
F: rust/kernel/platform.rs
|
||||
F: samples/rust/rust_debugfs.rs
|
||||
F: samples/rust/rust_debugfs_scoped.rs
|
||||
F: samples/rust/rust_driver_platform.rs
|
||||
F: samples/rust/rust_driver_faux.rs
|
||||
|
||||
@@ -19574,6 +19593,7 @@ C: irc://irc.oftc.net/linux-pci
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
|
||||
F: rust/helpers/pci.c
|
||||
F: rust/kernel/pci.rs
|
||||
F: rust/kernel/pci/
|
||||
F: samples/rust/rust_driver_pci.rs
|
||||
|
||||
PCIE BANDWIDTH CONTROLLER
|
||||
|
||||
+12
-15
@@ -171,17 +171,18 @@
|
||||
static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id,
|
||||
const struct auxiliary_device *auxdev)
|
||||
{
|
||||
const char *auxdev_name = dev_name(&auxdev->dev);
|
||||
const char *p = strrchr(auxdev_name, '.');
|
||||
int match_size;
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
match_size = p - auxdev_name;
|
||||
|
||||
for (; id->name[0]; id++) {
|
||||
const char *p = strrchr(dev_name(&auxdev->dev), '.');
|
||||
int match_size;
|
||||
|
||||
if (!p)
|
||||
continue;
|
||||
match_size = p - dev_name(&auxdev->dev);
|
||||
|
||||
/* use dev_name(&auxdev->dev) prefix before last '.' char to match to */
|
||||
if (strlen(id->name) == match_size &&
|
||||
!strncmp(dev_name(&auxdev->dev), id->name, match_size))
|
||||
!strncmp(auxdev_name, id->name, match_size))
|
||||
return id;
|
||||
}
|
||||
return NULL;
|
||||
@@ -217,17 +218,14 @@ static int auxiliary_bus_probe(struct device *dev)
|
||||
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
|
||||
int ret;
|
||||
|
||||
ret = dev_pm_domain_attach(dev, PD_FLAG_ATTACH_POWER_ON);
|
||||
ret = dev_pm_domain_attach(dev, PD_FLAG_ATTACH_POWER_ON |
|
||||
PD_FLAG_DETACH_POWER_OFF);
|
||||
if (ret) {
|
||||
dev_warn(dev, "Failed to attach to PM Domain : %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = auxdrv->probe(auxdev, auxiliary_match_id(auxdrv->id_table, auxdev));
|
||||
if (ret)
|
||||
dev_pm_domain_detach(dev, true);
|
||||
|
||||
return ret;
|
||||
return auxdrv->probe(auxdev, auxiliary_match_id(auxdrv->id_table, auxdev));
|
||||
}
|
||||
|
||||
static void auxiliary_bus_remove(struct device *dev)
|
||||
@@ -237,7 +235,6 @@ static void auxiliary_bus_remove(struct device *dev)
|
||||
|
||||
if (auxdrv->remove)
|
||||
auxdrv->remove(auxdev);
|
||||
dev_pm_domain_detach(dev, true);
|
||||
}
|
||||
|
||||
static void auxiliary_bus_shutdown(struct device *dev)
|
||||
|
||||
+23
-4
@@ -3994,8 +3994,8 @@ const char *device_get_devnode(const struct device *dev,
|
||||
/**
|
||||
* device_for_each_child - device child iterator.
|
||||
* @parent: parent struct device.
|
||||
* @fn: function to be called for each device.
|
||||
* @data: data for the callback.
|
||||
* @fn: function to be called for each device.
|
||||
*
|
||||
* Iterate over @parent's child devices, and call @fn for each,
|
||||
* passing it @data.
|
||||
@@ -4024,8 +4024,8 @@ EXPORT_SYMBOL_GPL(device_for_each_child);
|
||||
/**
|
||||
* device_for_each_child_reverse - device child iterator in reversed order.
|
||||
* @parent: parent struct device.
|
||||
* @fn: function to be called for each device.
|
||||
* @data: data for the callback.
|
||||
* @fn: function to be called for each device.
|
||||
*
|
||||
* Iterate over @parent's child devices, and call @fn for each,
|
||||
* passing it @data.
|
||||
@@ -4055,8 +4055,8 @@ EXPORT_SYMBOL_GPL(device_for_each_child_reverse);
|
||||
* device_for_each_child_reverse_from - device child iterator in reversed order.
|
||||
* @parent: parent struct device.
|
||||
* @from: optional starting point in child list
|
||||
* @fn: function to be called for each device.
|
||||
* @data: data for the callback.
|
||||
* @fn: function to be called for each device.
|
||||
*
|
||||
* Iterate over @parent's child devices, starting at @from, and call @fn
|
||||
* for each, passing it @data. This helper is identical to
|
||||
@@ -4089,8 +4089,8 @@ EXPORT_SYMBOL_GPL(device_for_each_child_reverse_from);
|
||||
/**
|
||||
* device_find_child - device iterator for locating a particular device.
|
||||
* @parent: parent struct device
|
||||
* @match: Callback function to check device
|
||||
* @data: Data to pass to match function
|
||||
* @match: Callback function to check device
|
||||
*
|
||||
* This is similar to the device_for_each_child() function above, but it
|
||||
* returns a reference to a device that is 'found' for later use, as
|
||||
@@ -5278,6 +5278,25 @@ void device_set_node(struct device *dev, struct fwnode_handle *fwnode)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_set_node);
|
||||
|
||||
/**
|
||||
* get_dev_from_fwnode - Obtain a reference count of the struct device the
|
||||
* struct fwnode_handle is associated with.
|
||||
* @fwnode: The pointer to the struct fwnode_handle to obtain the struct device
|
||||
* reference count of.
|
||||
*
|
||||
* This function obtains a reference count of the device the device pointer
|
||||
* embedded in the struct fwnode_handle points to.
|
||||
*
|
||||
* Note that the struct device pointer embedded in struct fwnode_handle does
|
||||
* *not* have a reference count of the struct device itself.
|
||||
*
|
||||
* Hence, it is a UAF (and thus a bug) to call this function if the caller can't
|
||||
* guarantee that the last reference count of the corresponding struct device is
|
||||
* not dropped concurrently.
|
||||
*
|
||||
* This is possible since struct fwnode_handle has its own reference count and
|
||||
* hence can out-live the struct device it is associated with.
|
||||
*/
|
||||
struct device *get_dev_from_fwnode(struct fwnode_handle *fwnode)
|
||||
{
|
||||
return get_device((fwnode)->dev);
|
||||
|
||||
+1
-1
@@ -325,7 +325,7 @@ static void cpu_device_release(struct device *dev)
|
||||
* This is an empty function to prevent the driver core from spitting a
|
||||
* warning at us. Yes, I know this is directly opposite of what the
|
||||
* documentation for the driver core and kobjects say, and the author
|
||||
* of this code has already been publically ridiculed for doing
|
||||
* of this code has already been publicly ridiculed for doing
|
||||
* something as foolish as this. However, at this point in time, it is
|
||||
* the only way to handle the issue of statically allocated cpu
|
||||
* devices. The different architectures will have their cpu device
|
||||
|
||||
@@ -155,6 +155,7 @@ struct faux_device *faux_device_create_with_groups(const char *name,
|
||||
dev->parent = &faux_bus_root;
|
||||
dev->bus = &faux_bus_type;
|
||||
dev_set_name(dev, "%s", name);
|
||||
device_set_pm_not_required(dev);
|
||||
|
||||
ret = device_add(dev);
|
||||
if (ret) {
|
||||
|
||||
@@ -844,7 +844,7 @@ swnode_register(const struct software_node *node, struct swnode *parent,
|
||||
* of this function or by ordering the array such that parent comes before
|
||||
* child.
|
||||
*/
|
||||
int software_node_register_node_group(const struct software_node **node_group)
|
||||
int software_node_register_node_group(const struct software_node * const *node_group)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
@@ -877,8 +877,7 @@ EXPORT_SYMBOL_GPL(software_node_register_node_group);
|
||||
* remove the nodes individually, in the correct order (child before
|
||||
* parent).
|
||||
*/
|
||||
void software_node_unregister_node_group(
|
||||
const struct software_node **node_group)
|
||||
void software_node_unregister_node_group(const struct software_node * const *node_group)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use kernel::{auxiliary, bindings, c_str, device::Core, pci, prelude::*, sizes::SZ_16M, sync::Arc};
|
||||
use kernel::{
|
||||
auxiliary, c_str,
|
||||
device::Core,
|
||||
pci,
|
||||
pci::{Class, ClassMask, Vendor},
|
||||
prelude::*,
|
||||
sizes::SZ_16M,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::gpu::Gpu;
|
||||
|
||||
@@ -18,10 +26,25 @@ kernel::pci_device_table!(
|
||||
PCI_TABLE,
|
||||
MODULE_PCI_TABLE,
|
||||
<NovaCore as pci::Driver>::IdInfo,
|
||||
[(
|
||||
pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_NVIDIA, bindings::PCI_ANY_ID as u32),
|
||||
()
|
||||
)]
|
||||
[
|
||||
// Modern NVIDIA GPUs will show up as either VGA or 3D controllers.
|
||||
(
|
||||
pci::DeviceId::from_class_and_vendor(
|
||||
Class::DISPLAY_VGA,
|
||||
ClassMask::ClassSubclass,
|
||||
Vendor::NVIDIA
|
||||
),
|
||||
()
|
||||
),
|
||||
(
|
||||
pci::DeviceId::from_class_and_vendor(
|
||||
Class::DISPLAY_3D,
|
||||
ClassMask::ClassSubclass,
|
||||
Vendor::NVIDIA
|
||||
),
|
||||
()
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
impl pci::Driver for NovaCore {
|
||||
|
||||
+5
-17
@@ -97,12 +97,9 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
|
||||
count = size - pos;
|
||||
}
|
||||
|
||||
if (!battr->read && !battr->read_new)
|
||||
if (!battr->read)
|
||||
return -EIO;
|
||||
|
||||
if (battr->read_new)
|
||||
return battr->read_new(of->file, kobj, battr, buf, pos, count);
|
||||
|
||||
return battr->read(of->file, kobj, battr, buf, pos, count);
|
||||
}
|
||||
|
||||
@@ -161,12 +158,9 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
if (!battr->write && !battr->write_new)
|
||||
if (!battr->write)
|
||||
return -EIO;
|
||||
|
||||
if (battr->write_new)
|
||||
return battr->write_new(of->file, kobj, battr, buf, pos, count);
|
||||
|
||||
return battr->write(of->file, kobj, battr, buf, pos, count);
|
||||
}
|
||||
|
||||
@@ -335,19 +329,13 @@ int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
|
||||
const struct kernfs_ops *ops;
|
||||
struct kernfs_node *kn;
|
||||
|
||||
if (battr->read && battr->read_new)
|
||||
return -EINVAL;
|
||||
|
||||
if (battr->write && battr->write_new)
|
||||
return -EINVAL;
|
||||
|
||||
if (battr->mmap)
|
||||
ops = &sysfs_bin_kfops_mmap;
|
||||
else if ((battr->read || battr->read_new) && (battr->write || battr->write_new))
|
||||
else if (battr->read && battr->write)
|
||||
ops = &sysfs_bin_kfops_rw;
|
||||
else if (battr->read || battr->read_new)
|
||||
else if (battr->read)
|
||||
ops = &sysfs_bin_kfops_ro;
|
||||
else if (battr->write || battr->write_new)
|
||||
else if (battr->write)
|
||||
ops = &sysfs_bin_kfops_wo;
|
||||
else
|
||||
ops = &sysfs_file_kfops_empty;
|
||||
|
||||
@@ -851,6 +851,9 @@ static inline bool device_pm_not_required(struct device *dev)
|
||||
static inline void device_set_pm_not_required(struct device *dev)
|
||||
{
|
||||
dev->power.no_pm = true;
|
||||
#ifdef CONFIG_PM
|
||||
dev->power.no_callbacks = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void dev_pm_syscore_device(struct device *dev, bool val)
|
||||
|
||||
@@ -574,8 +574,8 @@ const struct software_node *
|
||||
software_node_find_by_name(const struct software_node *parent,
|
||||
const char *name);
|
||||
|
||||
int software_node_register_node_group(const struct software_node **node_group);
|
||||
void software_node_unregister_node_group(const struct software_node **node_group);
|
||||
int software_node_register_node_group(const struct software_node * const *node_group);
|
||||
void software_node_unregister_node_group(const struct software_node * const *node_group);
|
||||
|
||||
int software_node_register(const struct software_node *node);
|
||||
void software_node_unregister(const struct software_node *node);
|
||||
|
||||
@@ -106,10 +106,7 @@ struct attribute_group {
|
||||
const struct bin_attribute *,
|
||||
int);
|
||||
struct attribute **attrs;
|
||||
union {
|
||||
const struct bin_attribute *const *bin_attrs;
|
||||
const struct bin_attribute *const *bin_attrs_new;
|
||||
};
|
||||
const struct bin_attribute *const *bin_attrs;
|
||||
};
|
||||
|
||||
#define SYSFS_PREALLOC 010000
|
||||
@@ -293,7 +290,7 @@ __ATTRIBUTE_GROUPS(_name)
|
||||
|
||||
#define BIN_ATTRIBUTE_GROUPS(_name) \
|
||||
static const struct attribute_group _name##_group = { \
|
||||
.bin_attrs_new = _name##_attrs, \
|
||||
.bin_attrs = _name##_attrs, \
|
||||
}; \
|
||||
__ATTRIBUTE_GROUPS(_name)
|
||||
|
||||
@@ -308,12 +305,8 @@ struct bin_attribute {
|
||||
struct address_space *(*f_mapping)(void);
|
||||
ssize_t (*read)(struct file *, struct kobject *, const struct bin_attribute *,
|
||||
char *, loff_t, size_t);
|
||||
ssize_t (*read_new)(struct file *, struct kobject *, const struct bin_attribute *,
|
||||
char *, loff_t, size_t);
|
||||
ssize_t (*write)(struct file *, struct kobject *, const struct bin_attribute *,
|
||||
char *, loff_t, size_t);
|
||||
ssize_t (*write_new)(struct file *, struct kobject *,
|
||||
const struct bin_attribute *, char *, loff_t, size_t);
|
||||
loff_t (*llseek)(struct file *, struct kobject *, const struct bin_attribute *,
|
||||
loff_t, int);
|
||||
int (*mmap)(struct file *, struct kobject *, const struct bin_attribute *attr,
|
||||
|
||||
@@ -12234,7 +12234,7 @@ static const struct attribute_group *pmu_dev_groups[] = {
|
||||
};
|
||||
|
||||
static int pmu_bus_running;
|
||||
static struct bus_type pmu_bus = {
|
||||
static const struct bus_type pmu_bus = {
|
||||
.name = "event_source",
|
||||
.dev_groups = pmu_dev_groups,
|
||||
};
|
||||
|
||||
@@ -46,12 +46,14 @@
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/device/faux.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/errname.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "dma.c"
|
||||
#include "drm.c"
|
||||
#include "err.c"
|
||||
#include "irq.c"
|
||||
#include "fs.c"
|
||||
#include "io.c"
|
||||
#include "jump_label.c"
|
||||
@@ -36,6 +37,7 @@
|
||||
#include "pid_namespace.c"
|
||||
#include "platform.c"
|
||||
#include "poll.c"
|
||||
#include "processor.c"
|
||||
#include "property.c"
|
||||
#include "rbtree.c"
|
||||
#include "rcu.c"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
int rust_helper_request_irq(unsigned int irq, irq_handler_t handler,
|
||||
unsigned long flags, const char *name, void *dev)
|
||||
{
|
||||
return request_irq(irq, handler, flags, name, dev);
|
||||
}
|
||||
@@ -2,6 +2,16 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
u16 rust_helper_pci_dev_id(struct pci_dev *dev)
|
||||
{
|
||||
return PCI_DEVID(dev->bus->number, dev->devfn);
|
||||
}
|
||||
|
||||
resource_size_t rust_helper_pci_resource_start(struct pci_dev *pdev, int bar)
|
||||
{
|
||||
return pci_resource_start(pdev, bar);
|
||||
}
|
||||
|
||||
resource_size_t rust_helper_pci_resource_len(struct pci_dev *pdev, int bar)
|
||||
{
|
||||
return pci_resource_len(pdev, bar);
|
||||
@@ -11,3 +21,11 @@ bool rust_helper_dev_is_pci(const struct device *dev)
|
||||
{
|
||||
return dev_is_pci(dev);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PCI_MSI
|
||||
int rust_helper_pci_irq_vector(struct pci_dev *pdev, unsigned int nvec)
|
||||
{
|
||||
return pci_irq_vector(pdev, nvec);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/processor.h>
|
||||
|
||||
void rust_helper_cpu_relax(void)
|
||||
{
|
||||
cpu_relax();
|
||||
}
|
||||
@@ -55,7 +55,7 @@ impl<T: Driver + 'static> Adapter<T> {
|
||||
extern "C" fn probe_callback(
|
||||
adev: *mut bindings::auxiliary_device,
|
||||
id: *const bindings::auxiliary_device_id,
|
||||
) -> kernel::ffi::c_int {
|
||||
) -> c_int {
|
||||
// SAFETY: The auxiliary bus only ever calls the probe callback with a valid pointer to a
|
||||
// `struct auxiliary_device`.
|
||||
//
|
||||
@@ -245,7 +245,7 @@ kernel::impl_device_context_deref!(unsafe { Device });
|
||||
kernel::impl_device_context_into_aref!(Device);
|
||||
|
||||
// SAFETY: Instances of `Device` are always reference-counted.
|
||||
unsafe impl crate::types::AlwaysRefCounted for Device {
|
||||
unsafe impl crate::sync::aref::AlwaysRefCounted for Device {
|
||||
fn inc_ref(&self) {
|
||||
// SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
|
||||
unsafe { bindings::get_device(self.as_ref().as_raw()) };
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2025 Google LLC.
|
||||
|
||||
//! Adapters which allow the user to supply a write or read implementation as a value rather
|
||||
//! than a trait implementation. If provided, it will override the trait implementation.
|
||||
|
||||
use super::{Reader, Writer};
|
||||
use crate::prelude::*;
|
||||
use crate::uaccess::UserSliceReader;
|
||||
use core::fmt;
|
||||
use core::fmt::Formatter;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::Deref;
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// To implement this trait, it must be safe to cast a `&Self` to a `&Inner`.
|
||||
/// It is intended for use in unstacking adapters out of `FileOps` backings.
|
||||
pub(crate) unsafe trait Adapter {
|
||||
type Inner;
|
||||
}
|
||||
|
||||
/// Adapter to implement `Reader` via a callback with the same representation as `T`.
|
||||
///
|
||||
/// * Layer it on top of `WriterAdapter` if you want to add a custom callback for `write`.
|
||||
/// * Layer it on top of `NoWriter` to pass through any support present on the underlying type.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// If an instance for `WritableAdapter<_, W>` is constructed, `W` is inhabited.
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct WritableAdapter<D, W> {
|
||||
inner: D,
|
||||
_writer: PhantomData<W>,
|
||||
}
|
||||
|
||||
// SAFETY: Stripping off the adapter only removes constraints
|
||||
unsafe impl<D, W> Adapter for WritableAdapter<D, W> {
|
||||
type Inner = D;
|
||||
}
|
||||
|
||||
impl<D: Writer, W> Writer for WritableAdapter<D, W> {
|
||||
fn write(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.write(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Deref, W> Reader for WritableAdapter<D, W>
|
||||
where
|
||||
W: Fn(&D::Target, &mut UserSliceReader) -> Result + Send + Sync + 'static,
|
||||
{
|
||||
fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
|
||||
// SAFETY: WritableAdapter<_, W> can only be constructed if W is inhabited
|
||||
let w: &W = unsafe { materialize_zst() };
|
||||
w(self.inner.deref(), reader)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adapter to implement `Writer` via a callback with the same representation as `T`.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// If an instance for `FormatAdapter<_, F>` is constructed, `F` is inhabited.
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct FormatAdapter<D, F> {
|
||||
inner: D,
|
||||
_formatter: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<D, F> Deref for FormatAdapter<D, F> {
|
||||
type Target = D;
|
||||
fn deref(&self) -> &D {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<D, F> Writer for FormatAdapter<D, F>
|
||||
where
|
||||
F: Fn(&D, &mut Formatter<'_>) -> fmt::Result + 'static,
|
||||
{
|
||||
fn write(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
// SAFETY: FormatAdapter<_, F> can only be constructed if F is inhabited
|
||||
let f: &F = unsafe { materialize_zst() };
|
||||
f(&self.inner, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Stripping off the adapter only removes constraints
|
||||
unsafe impl<D, F> Adapter for FormatAdapter<D, F> {
|
||||
type Inner = D;
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub(crate) struct NoWriter<D> {
|
||||
inner: D,
|
||||
}
|
||||
|
||||
// SAFETY: Stripping off the adapter only removes constraints
|
||||
unsafe impl<D> Adapter for NoWriter<D> {
|
||||
type Inner = D;
|
||||
}
|
||||
|
||||
impl<D> Deref for NoWriter<D> {
|
||||
type Target = D;
|
||||
fn deref(&self) -> &D {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
/// For types with a unique value, produce a static reference to it.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller asserts that F is inhabited
|
||||
unsafe fn materialize_zst<F>() -> &'static F {
|
||||
const { assert!(core::mem::size_of::<F>() == 0) };
|
||||
let zst_dangle: core::ptr::NonNull<F> = core::ptr::NonNull::dangling();
|
||||
// SAFETY: While the pointer is dangling, it is a dangling pointer to a ZST, based on the
|
||||
// assertion above. The type is also inhabited, by the caller's assertion. This means
|
||||
// we can materialize it.
|
||||
unsafe { zst_dangle.as_ref() }
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user