Char / Misc and documentation fixes for 7.2-rc7

Here are some small char/misc and nvmem and documentation fixes for
 7.2-rc7 to resolve some reported issues.  Included in here are:
   - updates to the documentation for the kernel threat model and
     security bugs to get the LLMs to actually follow what we have been
     asking them to do (i.e. not claim security issues for things we do
     not consider security issues.)
   - nvmem driver fixes which required a tiny "layout" driver to be
     added.
   - fastrpc driver fixes
   - mei driver fix
   - counter driver fix
   - binder driver fix
 
 All of these have been in linux-next this week with no reported
 problems.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCandLdw8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+yldzACZAVaM2/I0hIeTnoBqRFIZBcroUQYAoNk5zQSW
 qYG0DWUf4LJwj9WPQWIS
 =e+LJ
 -----END PGP SIGNATURE-----

Merge tag 'char-misc-7.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char / misc and documentation fixes from Greg KH:
 "Here are some small char/misc and nvmem and documentation fixes for
  7.2-rc7 to resolve some reported issues.  Included in here are:

   - updates to the documentation for the kernel threat model and
     security bugs to get the LLMs to actually follow what we have been
     asking them to do (i.e. not claim security issues for things we do
     not consider security issues.)

   - nvmem driver fixes which required a tiny "layout" driver to be
     added.

   - fastrpc driver fixes

   - mei driver fix

   - counter driver fix

   - binder driver fix

  All of these have been in linux-next this week with no reported
  problems"

* tag 'char-misc-7.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  docs: security-bugs: clarify some mandatory steps for AI reports
  docs: coding-assistant: explain important steps when looking for bugs
  docs: security-bugs: clarify what counts as a valid version
  docs: threat-model: move fake devices out of "non production use"
  docs: threat-model: clarify "security bug" vs "vulnerability"
  counter: microchip-tcb-capture: Fix DT channel validation
  mei: pull kvfree out of spinlock
  rust_binder: do not query current thread for all ioctls
  nvmem: layouts: Add fixed-layout driver
  nvmem: apple-spmi-nvmem: wrap regmap calls to satisfy CFI
  misc: fastrpc: fix memory leak in fastrpc_channel_ctx_free
  misc: fastrpc: fix channel ctx ref leak when session alloc fails
  misc: fastrpc: take fl->lock when moving mmaps on interrupted invoke
  misc: fastrpc: Remove buffer from list prior to unmap operation
  misc: fastrpc: Fix initial memory allocation for Audio PD memory pool
This commit is contained in:
Linus Torvalds 2026-08-08 16:25:59 -07:00
commit 5668ba2304
15 changed files with 220 additions and 77 deletions

View File

@ -57,3 +57,40 @@ Basic development tools (git, gcc, make, editors) should not be listed.
Example::
Assisted-by: Claude:claude-3-opus coccinelle sparse
Procedure for finding and fixing bugs
=====================================
When an AI assistant is used to find and fix bugs, it **MUST** follow at least
these steps:
1. Before starting, read the whole process documentation listed above, as well
as any other document mentioned in the request. Do not rely on isolated
parts found by keyword search.
2. Note the commit ID and Locate a bug as instructed.
3. For any bug found that is not trivial, verify that it looks real by
attempting to create a reproducer to demonstrate it. Lacking it may cause
the report to be ignored, as many unverified bug reports sent to maintainers
happen to be invalid. Stop here if it finally looks wrong.
4. Write a fix for the bug. This part is not optional: except in a few very
rare cases, an AI assistant able to find a bug is able to fix it. Note that
fixes written in the same session as used to find the bug will generally
lead to better and more accurate fixes as the LLM's reasoning context
remains present.
5. Build and verify that the fix works either using the reproducer or by
re-running a complete analysis; drop any fix that doesn't work and try
another one. The fix must not add build warnings and must pass the
checkpatch.pl checks (see submitting-patches.rst).
6. Commit the working fix with a detailed message describing the problem, the
solution and a Fixes tag. Do not add a Signed-off-by tag, and add an
Assisted-by tag, as described above.
7. Identify the maintainers and lists using scripts/get_maintainer.pl.
Documentation/process/security-bugs.rst shows how to do that.
8. Indicate what could not be done. If the fix could not be built or tested, or
if no reproducer could be produced, say so explicitly: maintainers currently
waste too much time analyzing unverified reports and untested fixes.
9. Read Documentation/process/threat-model.rst to determine whether the bug is
a vulnerability or a regular bug, and leave the result to the reporter for
review (the assistant must never send anything itself). Regular bugs are
submitted as described in Documentation/process/submitting-patches.rst,
vulnerabilities as described in Documentation/process/security-bugs.rst.

View File

@ -18,6 +18,10 @@ information is helpful. The following information are absolutely necessary in
**any** security bug report:
* **affected kernel version range**: with no version indication, your report
will not be processed. Note that a time-dependent version such as "latest
mainline" is not acceptable. A stable identifier such as a commit ID or an
exact version is required. Versions designating kernels not coming from
kernel.org (such as distro kernels) are meaningless to maintainers and
will not be processed. A significant part of reports are for bugs that
have already been fixed, so it is extremely important that vulnerabilities
are verified on recent versions (development tree or latest stable
@ -225,6 +229,28 @@ there is no need to consume a maintainer's time with an unimportant report. If
the issue is clearly trivial and publicly discoverable, you should report it
directly to the public mailing lists.
At the very least, when using an AI assistant to find and report bugs, make the
assistant read this file and threat-model.rst before proceeding, and have it
follow the procedure described in coding-assistants.rst: work on an up-to-date
mainline tree and note the commit ID, verify the bug is real, write a fix,
build it warning-free and checkpatch-clean, commit it with a Fixes tag, and
identify the maintainers with get_maintainer.pl.
On top of that procedure, the AI assistant **MUST**:
1. Prepare a plain-text report explaining the problem. It must contain the
four items listed at the top of this file as absolutely necessary: the
affected version or commit ID noted while following the procedure above,
the description of the problem, the reproducer or its status, and the
triggering conditions.
2. Start the report with a temporary section listing the recipients' addresses
(maintainers+list for the patch, maintainers only for the report and
reproducer), and with instructions reminding the reporter to check that
their email client is properly setup (see email-clients.rst), and leave it
to the reporter to remove that temporary section.
A more detailed process is covered at https://github.com/masoncl/kres.git.
Sending the report
------------------

View File

@ -98,11 +98,11 @@ measures whose purpose is to avoid crossing a security boundary when certain
classes of bugs are found, but a failure of these extra protections do not
constitute a vulnerability alone.
What does not constitute a security bug
---------------------------------------
What classes of problems are not considered vulnerabilities
-----------------------------------------------------------
In the Linux kernel's threat model, the following classes of problems are
**NOT** considered as Linux Kernel security bugs. However, when it is believed
**NOT** considered Linux Kernel vulnerabilities. However, when it is believed
that the kernel could do better, they should be reported, so that they can be
reviewed and fixed where reasonably possible, but they will be handled as any
regular bug:
@ -111,8 +111,8 @@ regular bug:
* outdated kernels and particularly end-of-life branches are out of the scope
of the kernel's threat model: administrators are responsible for keeping
their system up to date. For a bug to qualify as a security bug, it must be
demonstrated that it affects actively maintained versions.
their system up to date. For a bug to qualify as a vulnerability, it must
be demonstrated that it affects actively maintained versions.
* build-level: changes to the kernel configuration that are explicitly
documented as lowering the security level (e.g. ``CONFIG_NOMMU``), or
@ -178,9 +178,6 @@ regular bug:
involving tens of millions of threads, tens of thousands of CPUs,
unrealistic CPU frequencies, RAM sizes or disk capacities, network speeds).
* issues whose reproduction requires hardware modification or emulation,
including fake USB devices that pretend to be another one.
* as well as issues that can be triggered at a cost that is orders of
magnitude higher than the expected benefits (e.g. fully functional keyboard
emulator only to retrieve 7 uninitialized bytes in a structure, or
@ -208,19 +205,27 @@ regular bug:
messages.
* Leaks of kernel memory addresses/pointers do not constitute an immediately
exploitable vector and are not security bugs, though they must be reported
and fixed.
exploitable vector and are not vulnerabilities, though they must be
reported and fixed.
* **Crafted file system images**:
* **Non-conforming devices and media**:
Drivers are implemented against a specification. When a device or a storage
medium violates the specification its driver was written against, the
resulting misbehaviour is a regular bug to be fixed, not a vulnerability,
unless the driver is specifically documented as being hardened against
hostile inputs. The following are therefore not considered vulnerabilities:
* bugs triggered by mounting a corrupted or maliciously crafted file system
image are generally not security bugs, as the kernel assumes the underlying
storage media is under the administrator's control, unless the filesystem
driver is specifically documented as being hardened against untrusted media.
* issues that are resolved, mitigated, or detected by running a filesystem
image: mounting a block device is a privileged operation (see above), and
the administrator is responsible for the media they mount. This includes
issues that are resolved, mitigated, or detected by running a filesystem
consistency check (fsck) on the image prior to mounting.
* bugs whose reproduction requires hardware modification or emulation,
including fake USB devices that pretend to be another one, or devices
reporting values outside their documented ranges.
* **Physical access**:
Issues that require physical access to the machine, hardware modification, or
@ -232,4 +237,4 @@ regular bug:
* **Functional and performance regressions**:
Any issue that can be mitigated by setting proper permissions and limits
doesn't qualify as a security bug.
doesn't qualify as a vulnerability.

View File

@ -10125,6 +10125,11 @@ F: drivers/base/firmware_loader/
F: rust/kernel/firmware.rs
F: include/linux/firmware.h
FIXED-LAYOUT NVMEM LAYOUT DRIVER
M: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
S: Maintained
F: drivers/nvmem/layouts/fixed-layout.c
FLEXTIMER FTM-QUADDEC DRIVER
M: Patrick Havelange <patrick.havelange@essensium.com>
L: linux-iio@vger.kernel.org

View File

@ -1586,6 +1586,10 @@ fn ioctl_write_only(
cmd: u32,
reader: &mut UserSliceReader,
) -> Result {
if cmd == uapi::BINDER_FREEZE {
return ioctl_freeze(reader);
}
let thread = this.get_current_thread()?;
match cmd {
uapi::BINDER_SET_MAX_THREADS => this.set_max_threads(reader.read()?),
@ -1597,7 +1601,6 @@ fn ioctl_write_only(
uapi::BINDER_ENABLE_ONEWAY_SPAM_DETECTION => {
this.set_oneway_spam_detection_enabled(reader.read()?)
}
uapi::BINDER_FREEZE => ioctl_freeze(reader)?,
_ => return Err(EINVAL),
}
Ok(())
@ -1612,15 +1615,16 @@ fn ioctl_write_read(
cmd: u32,
data: UserSlice,
) -> Result {
let thread = this.get_current_thread()?;
let blocking = (file.flags() & file::flags::O_NONBLOCK) == 0;
match cmd {
uapi::BINDER_WRITE_READ => thread.write_read(data, blocking)?,
uapi::BINDER_WRITE_READ => this.get_current_thread()?.write_read(data, blocking)?,
uapi::BINDER_GET_NODE_DEBUG_INFO => this.get_node_debug_info(data)?,
uapi::BINDER_GET_NODE_INFO_FOR_REF => this.get_node_info_from_ref(data)?,
uapi::BINDER_VERSION => this.version(data)?,
uapi::BINDER_GET_FROZEN_INFO => get_frozen_status(data)?,
uapi::BINDER_GET_EXTENDED_ERROR => thread.get_extended_error(data)?,
uapi::BINDER_GET_EXTENDED_ERROR => {
this.get_current_thread()?.get_extended_error(data)?
}
_ => return Err(EINVAL),
}
Ok(())

View File

@ -483,7 +483,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
char clk_name[7];
struct regmap *regmap;
struct clk *clk[3];
int channel;
u32 channel;
int ret, i;
counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
@ -517,7 +517,7 @@ static int mchp_tc_probe(struct platform_device *pdev)
priv->channel[i] = channel;
snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
snprintf(clk_name, sizeof(clk_name), "t%u_clk", channel);
clk[i] = of_clk_get_by_name(np->parent, clk_name);
if (IS_ERR(clk[i])) {

View File

@ -492,6 +492,7 @@ static void fastrpc_channel_ctx_free(struct kref *ref)
cctx = container_of(ref, struct fastrpc_channel_ctx, refcount);
idr_destroy(&cctx->ctx_idr);
kfree(cctx);
}
@ -1305,10 +1306,12 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
}
if (err == -ERESTARTSYS) {
spin_lock(&fl->lock);
list_for_each_entry_safe(buf, b, &fl->mmaps, node) {
list_del(&buf->node);
list_add_tail(&buf->node, &fl->cctx->invoke_interrupted_mmaps);
}
spin_unlock(&fl->lock);
}
if (err)
@ -1370,7 +1373,9 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
err = PTR_ERR(name);
goto err;
}
inbuf.client_id = fl->client_id;
inbuf.namelen = init.namelen;
inbuf.pageslen = 0;
if (!fl->cctx->remote_heap) {
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen,
&fl->cctx->remote_heap);
@ -1393,12 +1398,10 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
goto err_map;
}
scm_done = true;
inbuf.pageslen = 1;
}
}
inbuf.client_id = fl->client_id;
inbuf.namelen = init.namelen;
inbuf.pageslen = 0;
fl->pd = USER_PD;
args[0].ptr = (u64)(uintptr_t)&inbuf;
@ -1673,7 +1676,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
dev_err(&cctx->rpdev->dev, "No session available\n");
mutex_destroy(&fl->mutex);
kfree(fl);
fastrpc_channel_ctx_put(cctx);
return -EBUSY;
}
@ -1889,9 +1892,6 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf *
&args[0]);
if (!err) {
dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr);
spin_lock(&fl->lock);
list_del(&buf->node);
spin_unlock(&fl->lock);
fastrpc_buf_free(buf);
} else {
dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr);
@ -1905,6 +1905,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp)
struct fastrpc_buf *buf = NULL, *iter, *b;
struct fastrpc_req_munmap req;
struct device *dev = fl->sctx->dev;
int err;
if (copy_from_user(&req, argp, sizeof(req)))
return -EFAULT;
@ -1912,6 +1913,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp)
spin_lock(&fl->lock);
list_for_each_entry_safe(iter, b, &fl->mmaps, node) {
if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) {
list_del(&iter->node);
buf = iter;
break;
}
@ -1924,7 +1926,14 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp)
return -EINVAL;
}
return fastrpc_req_munmap_impl(fl, buf);
err = fastrpc_req_munmap_impl(fl, buf);
if (err) {
spin_lock(&fl->lock);
list_add_tail(&buf->node, &fl->mmaps);
spin_unlock(&fl->lock);
}
return err;
}
static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)

View File

@ -425,18 +425,24 @@ static void mei_io_tx_list_free_cl(struct list_head *head,
}
/**
* mei_io_list_free_fp - free cb from a list that matches file pointer
* mei_io_rd_list_free_fp - free cb from a rd_completed list that matches file pointer
*
* @head: io list
* @cl: host client
* @fp: file pointer (matching cb file object), may be NULL
*/
static void mei_io_list_free_fp(struct list_head *head, const struct file *fp)
static void mei_io_rd_list_free_fp(struct mei_cl *cl, const struct file *fp)
{
struct mei_cl_cb *cb, *next;
LIST_HEAD(cmpl_list);
list_for_each_entry_safe(cb, next, head, list)
spin_lock(&cl->rd_completed_lock);
list_for_each_entry_safe(cb, next, &cl->rd_completed, list)
if (!fp || fp == cb->fp)
mei_io_cb_free(cb);
list_move(&cb->list, &cmpl_list);
spin_unlock(&cl->rd_completed_lock);
list_for_each_entry_safe(cb, next, &cmpl_list, list)
mei_io_cb_free(cb);
}
/**
@ -565,9 +571,7 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl);
mei_cl_free_pending(cl);
}
spin_lock(&cl->rd_completed_lock);
mei_io_list_free_fp(&cl->rd_completed, fp);
spin_unlock(&cl->rd_completed_lock);
mei_io_rd_list_free_fp(cl, fp);
return 0;
}
@ -1401,7 +1405,7 @@ void mei_cl_add_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
}
/**
* mei_cl_del_rd_completed - free read completed callback with lock
* mei_cl_del_rd_completed - unlink read completed callback with lock and free it
*
* @cl: host client
* @cb: callback block
@ -1410,8 +1414,9 @@ void mei_cl_add_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
void mei_cl_del_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
{
spin_lock(&cl->rd_completed_lock);
mei_io_cb_free(cb);
list_del_init(&cb->list);
spin_unlock(&cl->rd_completed_lock);
mei_io_cb_free(cb);
}
/**

View File

@ -18,6 +18,22 @@ static const struct regmap_config apple_spmi_regmap_config = {
.max_register = 0xffff,
};
static int apple_spmi_nvmem_read(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct regmap *map = priv;
return regmap_bulk_read(map, offset, val, bytes);
}
static int apple_spmi_nvmem_write(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct regmap *map = priv;
return regmap_bulk_write(map, offset, val, bytes);
}
static int apple_spmi_nvmem_probe(struct spmi_device *sdev)
{
struct regmap *regmap;
@ -28,8 +44,8 @@ static int apple_spmi_nvmem_probe(struct spmi_device *sdev)
.word_size = 1,
.stride = 1,
.size = 0xffff,
.reg_read = (void *)regmap_bulk_read,
.reg_write = (void *)regmap_bulk_write,
.reg_read = apple_spmi_nvmem_read,
.reg_write = apple_spmi_nvmem_write,
};
regmap = devm_regmap_init_spmi_ext(sdev, &apple_spmi_regmap_config);

View File

@ -786,7 +786,7 @@ static int nvmem_validate_keepouts(struct nvmem_device *nvmem)
return 0;
}
static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np)
int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np)
{
struct device *dev = &nvmem->dev;
const __be32 *addr;
@ -834,29 +834,13 @@ static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_nod
return 0;
}
EXPORT_SYMBOL_GPL(nvmem_add_cells_from_dt);
static int nvmem_add_cells_from_legacy_of(struct nvmem_device *nvmem)
{
return nvmem_add_cells_from_dt(nvmem, nvmem->dev.of_node);
}
static int nvmem_add_cells_from_fixed_layout(struct nvmem_device *nvmem)
{
struct device_node *layout_np;
int err = 0;
layout_np = of_nvmem_layout_get_container(nvmem);
if (!layout_np)
return 0;
if (of_device_is_compatible(layout_np, "fixed-layout"))
err = nvmem_add_cells_from_dt(nvmem, layout_np);
of_node_put(layout_np);
return err;
}
int nvmem_layout_register(struct nvmem_layout *layout)
{
int ret;
@ -1005,10 +989,6 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
goto err_remove_cells;
}
rval = nvmem_add_cells_from_fixed_layout(nvmem);
if (rval)
goto err_remove_cells;
dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
rval = device_add(&nvmem->dev);

View File

@ -35,6 +35,8 @@ struct nvmem_device {
bool sysfs_cells_populated;
};
int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np);
#if IS_ENABLED(CONFIG_OF)
int nvmem_layout_bus_register(void);
void nvmem_layout_bus_unregister(void);

View File

@ -125,11 +125,6 @@ static int nvmem_layout_create_device(struct nvmem_device *nvmem,
return 0;
}
static const struct of_device_id of_nvmem_layout_skip_table[] = {
{ .compatible = "fixed-layout", },
{}
};
static int nvmem_layout_bus_populate(struct nvmem_device *nvmem,
struct device_node *layout_dn)
{
@ -142,12 +137,6 @@ static int nvmem_layout_bus_populate(struct nvmem_device *nvmem,
return 0;
}
/* Fixed layouts are parsed manually somewhere else for now */
if (of_match_node(of_nvmem_layout_skip_table, layout_dn)) {
pr_debug("%s() - skipping %pOF node\n", __func__, layout_dn);
return 0;
}
if (of_node_check_flag(layout_dn, OF_POPULATED_BUS)) {
pr_debug("%s() - skipping %pOF, already populated\n",
__func__, layout_dn);

View File

@ -3,6 +3,7 @@
# Makefile for nvmem layouts.
#
obj-$(CONFIG_NVMEM_LAYOUTS) += fixed-layout.o
obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o

View File

@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2026 Bootlin
*
* Authors: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
*/
#include <linux/nvmem-provider.h>
#include <linux/of.h>
#include "../internals.h"
static int fixed_layout_add_cells(struct nvmem_layout *layout)
{
struct device_node *np;
int ret;
np = of_nvmem_layout_get_container(layout->nvmem);
if (!np)
return -ENOENT;
ret = nvmem_add_cells_from_dt(layout->nvmem, np);
of_node_put(np);
return ret;
}
static int fixed_layout_probe(struct nvmem_layout *layout)
{
layout->add_cells = fixed_layout_add_cells;
return nvmem_layout_register(layout);
}
static void fixed_layout_remove(struct nvmem_layout *layout)
{
nvmem_layout_unregister(layout);
}
static const struct of_device_id fixed_layout_of_match_table[] = {
{ .compatible = "fixed-layout", },
{},
};
static struct nvmem_layout_driver fixed_layout_layout = {
.driver = {
.name = "fixed-layout",
.of_match_table = fixed_layout_of_match_table,
},
.probe = fixed_layout_probe,
.remove = fixed_layout_remove,
};
module_nvmem_layout_driver(fixed_layout_layout);
MODULE_AUTHOR("Mathieu Dubois-Briand");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(of, fixed_layout_of_match_table);
MODULE_DESCRIPTION("NVMEM fixed-layout driver");

View File

@ -214,6 +214,12 @@ static inline int nvmem_layout_register(struct nvmem_layout *layout)
static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {}
static inline int nvmem_add_cells_from_dt(struct nvmem_device *nvmem,
struct device_node *np)
{
return -EOPNOTSUPP;
}
#endif /* CONFIG_NVMEM */
#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)