* [PATCH v5 08/21] nfsd: use RCU to protect fi_deleg_file
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
In-Reply-To: <20260522-dir-deleg-v5-0-542cddfad576@kernel.org>
fi_deleg_file can be NULLed by put_deleg_file() when fi_delegees drops
to zero during delegation teardown (e.g. DELEGRETURN). Concurrent
accesses from workqueue callbacks -- such as CB_NOTIFY -- can
dereference a NULL pointer if they race with this teardown.
Annotate fi_deleg_file with __rcu and convert all accessors to use
proper RCU primitives:
- rcu_assign_pointer() / RCU_INIT_POINTER() for stores
- rcu_dereference_protected() for reads under fi_lock or where
fi_delegees > 0 guarantees stability
This prepares for a subsequent patch that will use rcu_read_lock +
rcu_dereference + nfsd_file_get to safely acquire a reference from
the CB_NOTIFY callback path without holding fi_lock.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4layouts.c | 2 +-
fs/nfsd/nfs4state.c | 39 +++++++++++++++++++++++----------------
fs/nfsd/state.h | 2 +-
3 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index e3984c90792e..9ed2e3d65062 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -248,7 +248,7 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate,
NFSPROC4_CLNT_CB_LAYOUT);
if (parent->sc_type == SC_TYPE_DELEG)
- ls->ls_file = nfsd_file_get(fp->fi_deleg_file);
+ ls->ls_file = nfsd_file_get(rcu_dereference_protected(fp->fi_deleg_file, 1));
else
ls->ls_file = find_any_file(fp);
BUG_ON(!ls->ls_file);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 3efc53f0dde6..bd0517dfe881 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1212,7 +1212,9 @@ static void put_deleg_file(struct nfs4_file *fp)
spin_lock(&fp->fi_lock);
if (--fp->fi_delegees == 0) {
- swap(nf, fp->fi_deleg_file);
+ nf = rcu_dereference_protected(fp->fi_deleg_file,
+ lockdep_is_held(&fp->fi_lock));
+ rcu_assign_pointer(fp->fi_deleg_file, NULL);
swap(rnf, fp->fi_rdeleg_file);
}
spin_unlock(&fp->fi_lock);
@@ -1282,7 +1284,7 @@ static void nfsd_fsnotify_recalc_mask(struct nfsd_file *nf)
static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
{
struct nfs4_file *fp = dp->dl_stid.sc_file;
- struct nfsd_file *nf = fp->fi_deleg_file;
+ struct nfsd_file *nf = rcu_dereference_protected(fp->fi_deleg_file, 1);
WARN_ON_ONCE(!fp->fi_delegees);
@@ -3176,7 +3178,8 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st)
/* XXX: lease time, whether it's being recalled. */
spin_lock(&nf->fi_lock);
- file = nf->fi_deleg_file;
+ file = rcu_dereference_protected(nf->fi_deleg_file,
+ lockdep_is_held(&nf->fi_lock));
if (file) {
seq_puts(s, ", ");
nfs4_show_superblock(s, file);
@@ -4958,7 +4961,7 @@ static void nfsd4_file_init(const struct svc_fh *fh, struct nfs4_file *fp)
INIT_LIST_HEAD(&fp->fi_delegations);
INIT_LIST_HEAD(&fp->fi_clnt_odstate);
fh_copy_shallow(&fp->fi_fhandle, &fh->fh_handle);
- fp->fi_deleg_file = NULL;
+ RCU_INIT_POINTER(fp->fi_deleg_file, NULL);
fp->fi_rdeleg_file = NULL;
fp->fi_had_conflict = false;
fp->fi_share_deny = 0;
@@ -6110,7 +6113,7 @@ static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp, u32
fl->c.flc_type = deleg_is_read(dp->dl_type) ? F_RDLCK : F_WRLCK;
fl->c.flc_owner = (fl_owner_t)dp;
fl->c.flc_pid = current->tgid;
- fl->c.flc_file = dp->dl_stid.sc_file->fi_deleg_file->nf_file;
+ fl->c.flc_file = rcu_dereference_protected(dp->dl_stid.sc_file->fi_deleg_file, 1)->nf_file;
return fl;
}
@@ -6118,7 +6121,7 @@ static int nfsd4_check_conflicting_opens(struct nfs4_client *clp,
struct nfs4_file *fp)
{
struct nfs4_ol_stateid *st;
- struct file *f = fp->fi_deleg_file->nf_file;
+ struct file *f = rcu_dereference_protected(fp->fi_deleg_file, 1)->nf_file;
struct inode *ino = file_inode(f);
int writes;
@@ -6195,7 +6198,7 @@ nfsd4_verify_deleg_dentry(struct nfsd4_open *open, struct nfs4_file *fp,
exp_put(exp);
dput(child);
- if (child != file_dentry(fp->fi_deleg_file->nf_file))
+ if (child != file_dentry(rcu_dereference_protected(fp->fi_deleg_file, 1)->nf_file))
return -EAGAIN;
return 0;
@@ -6301,8 +6304,9 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
status = -EAGAIN;
else if (nfsd4_verify_setuid_write(open, nf))
status = -EAGAIN;
- else if (!fp->fi_deleg_file) {
- fp->fi_deleg_file = nf;
+ else if (!rcu_dereference_protected(fp->fi_deleg_file,
+ lockdep_is_held(&fp->fi_lock))) {
+ rcu_assign_pointer(fp->fi_deleg_file, nf);
/* increment early to prevent fi_deleg_file from being
* cleared */
fp->fi_delegees = 1;
@@ -6327,7 +6331,7 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
if (!fl)
goto out_clnt_odstate;
- status = kernel_setlease(fp->fi_deleg_file->nf_file,
+ status = kernel_setlease(rcu_dereference_protected(fp->fi_deleg_file, 1)->nf_file,
fl->c.flc_type, &fl, NULL);
if (fl)
locks_free_lease(fl);
@@ -6348,7 +6352,7 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
* Now that the deleg is set, check again to ensure that nothing
* raced in and changed the mode while we weren't looking.
*/
- status = nfsd4_verify_setuid_write(open, fp->fi_deleg_file);
+ status = nfsd4_verify_setuid_write(open, rcu_dereference_protected(fp->fi_deleg_file, 1));
if (status)
goto out_unlock;
@@ -6369,7 +6373,8 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
return dp;
out_unlock:
- kernel_setlease(fp->fi_deleg_file->nf_file, F_UNLCK, NULL, (void **)&dp);
+ kernel_setlease(rcu_dereference_protected(fp->fi_deleg_file, 1)->nf_file,
+ F_UNLCK, NULL, (void **)&dp);
out_clnt_odstate:
put_clnt_odstate(dp->dl_clnt_odstate);
nfs4_put_stid(&dp->dl_stid);
@@ -6526,8 +6531,9 @@ nfs4_open_delegation(struct svc_rqst *rqstp, struct nfsd4_open *open,
memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
- struct file *f = dp->dl_stid.sc_file->fi_deleg_file->nf_file;
+ struct file *f;
+ f = rcu_dereference_protected(dp->dl_stid.sc_file->fi_deleg_file, 1)->nf_file;
if (!nfsd4_add_rdaccess_to_wrdeleg(rqstp, open, fh, stp) ||
!nfs4_delegation_stat(dp, currentfh, &stat)) {
nfs4_put_stid(&dp->dl_stid);
@@ -9669,8 +9675,9 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate,
/* existing delegation? */
if (nfs4_delegation_exists(clp, fp)) {
status = -EAGAIN;
- } else if (!fp->fi_deleg_file) {
- fp->fi_deleg_file = nfsd_file_get(nf);
+ } else if (!rcu_dereference_protected(fp->fi_deleg_file,
+ lockdep_is_held(&fp->fi_lock))) {
+ rcu_assign_pointer(fp->fi_deleg_file, nfsd_file_get(nf));
fp->fi_delegees = 1;
} else {
++fp->fi_delegees;
@@ -9722,7 +9729,7 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate,
}
/* Something failed. Drop the lease and clean up the stid */
- kernel_setlease(fp->fi_deleg_file->nf_file, F_UNLCK, NULL, (void **)&dp);
+ kernel_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp);
out_put_stid:
nfs4_put_stid(&dp->dl_stid);
out_delegees:
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 790282781243..9c6e2e7abc82 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -698,7 +698,7 @@ struct nfs4_file {
*/
atomic_t fi_access[2];
u32 fi_share_deny;
- struct nfsd_file *fi_deleg_file;
+ struct nfsd_file __rcu *fi_deleg_file;
struct nfsd_file *fi_rdeleg_file;
int fi_delegees;
struct knfsd_fh fi_fhandle;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 07/21] nfsd: add callback encoding and decoding linkages for CB_NOTIFY
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
In-Reply-To: <20260522-dir-deleg-v5-0-542cddfad576@kernel.org>
Add routines for encoding and decoding CB_NOTIFY messages. These call
into the code generated by xdrgen to do the actual encoding and
decoding.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4callback.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
fs/nfsd/state.h | 8 ++++++++
fs/nfsd/xdr4cb.h | 12 ++++++++++++
3 files changed, 66 insertions(+)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 25bbf5b8814d..ea3e7deb06fa 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -865,6 +865,51 @@ static void encode_stateowner(struct xdr_stream *xdr, struct nfs4_stateowner *so
xdr_encode_opaque(p, so->so_owner.data, so->so_owner.len);
}
+static void nfs4_xdr_enc_cb_notify(struct rpc_rqst *req,
+ struct xdr_stream *xdr,
+ const void *data)
+{
+ const struct nfsd4_callback *cb = data;
+ struct nfs4_cb_compound_hdr hdr = {
+ .ident = 0,
+ .minorversion = cb->cb_clp->cl_minorversion,
+ };
+ struct CB_NOTIFY4args args = { };
+
+ WARN_ON_ONCE(hdr.minorversion == 0);
+
+ encode_cb_compound4args(xdr, &hdr);
+ encode_cb_sequence4args(xdr, cb, &hdr);
+
+ /*
+ * FIXME: get stateid and fh from delegation. Inline the cna_changes
+ * buffer, and zero it.
+ */
+ WARN_ON_ONCE(!xdrgen_encode_CB_NOTIFY4args(xdr, &args));
+
+ hdr.nops++;
+ encode_cb_nops(&hdr);
+}
+
+static int nfs4_xdr_dec_cb_notify(struct rpc_rqst *rqstp,
+ struct xdr_stream *xdr,
+ void *data)
+{
+ struct nfsd4_callback *cb = data;
+ struct nfs4_cb_compound_hdr hdr;
+ int status;
+
+ status = decode_cb_compound4res(xdr, &hdr);
+ if (unlikely(status))
+ return status;
+
+ status = decode_cb_sequence4res(xdr, cb);
+ if (unlikely(status || cb->cb_seq_status))
+ return status;
+
+ return decode_cb_op_status(xdr, OP_CB_NOTIFY, &cb->cb_status);
+}
+
static void nfs4_xdr_enc_cb_notify_lock(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
@@ -1026,6 +1071,7 @@ static const struct rpc_procinfo nfs4_cb_procedures[] = {
#ifdef CONFIG_NFSD_PNFS
PROC(CB_LAYOUT, COMPOUND, cb_layout, cb_layout),
#endif
+ PROC(CB_NOTIFY, COMPOUND, cb_notify, cb_notify),
PROC(CB_NOTIFY_LOCK, COMPOUND, cb_notify_lock, cb_notify_lock),
PROC(CB_OFFLOAD, COMPOUND, cb_offload, cb_offload),
PROC(CB_RECALL_ANY, COMPOUND, cb_recall_any, cb_recall_any),
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index e1c40f8b5d01..790282781243 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -190,6 +190,13 @@ struct nfs4_cb_fattr {
u64 ncf_cur_fsize;
};
+/*
+ * FIXME: the current backchannel encoder can't handle a send buffer longer
+ * than a single page (see bc_alloc/bc_free).
+ */
+#define NOTIFY4_EVENT_QUEUE_SIZE 3
+#define NOTIFY4_PAGE_ARRAY_SIZE 1
+
/*
* Represents a delegation stateid. The nfs4_client holds references to these
* and they are put when it is being destroyed or when the delegation is
@@ -774,6 +781,7 @@ enum nfsd4_cb_op {
NFSPROC4_CLNT_CB_NOTIFY_LOCK,
NFSPROC4_CLNT_CB_RECALL_ANY,
NFSPROC4_CLNT_CB_GETATTR,
+ NFSPROC4_CLNT_CB_NOTIFY,
};
/* Returns true iff a is later than b: */
diff --git a/fs/nfsd/xdr4cb.h b/fs/nfsd/xdr4cb.h
index f4e29c0c701c..b06d0170d7c4 100644
--- a/fs/nfsd/xdr4cb.h
+++ b/fs/nfsd/xdr4cb.h
@@ -33,6 +33,18 @@
cb_sequence_dec_sz + \
op_dec_sz)
+#define NFS4_enc_cb_notify_sz (cb_compound_enc_hdr_sz + \
+ cb_sequence_enc_sz + \
+ 1 + enc_stateid_sz + \
+ enc_nfs4_fh_sz + \
+ 1 + \
+ NOTIFY4_EVENT_QUEUE_SIZE * \
+ (2 + (NFS4_OPAQUE_LIMIT >> 2)))
+
+#define NFS4_dec_cb_notify_sz (cb_compound_dec_hdr_sz + \
+ cb_sequence_dec_sz + \
+ op_dec_sz)
+
#define NFS4_enc_cb_notify_lock_sz (cb_compound_enc_hdr_sz + \
cb_sequence_enc_sz + \
2 + 1 + \
--
2.54.0
^ permalink raw reply related
* [PATCH v5 06/21] nfsd: make nfsd4_callback_ops->prepare operation bool return
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
In-Reply-To: <20260522-dir-deleg-v5-0-542cddfad576@kernel.org>
For a CB_NOTIFY operation, we need to stop processing the callback
if an allocation fails. Change the ->prepare callback operation to
return true if processing should continue, and false otherwise.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4callback.c | 5 ++++-
fs/nfsd/nfs4layouts.c | 3 ++-
fs/nfsd/nfs4state.c | 6 ++++--
fs/nfsd/state.h | 6 +++---
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 50827405468d..25bbf5b8814d 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1715,7 +1715,10 @@ nfsd4_run_cb_work(struct work_struct *work)
if (!test_and_clear_bit(NFSD4_CALLBACK_REQUEUE, &cb->cb_flags)) {
if (cb->cb_ops && cb->cb_ops->prepare)
- cb->cb_ops->prepare(cb);
+ if (!cb->cb_ops->prepare(cb)) {
+ nfsd41_destroy_cb(cb);
+ return;
+ }
}
cb->cb_msg.rpc_cred = clp->cl_cb_cred;
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index f34320e4c2f4..e3984c90792e 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -652,7 +652,7 @@ nfsd4_cb_layout_fail(struct nfs4_layout_stateid *ls, struct nfsd_file *file)
}
}
-static void
+static bool
nfsd4_cb_layout_prepare(struct nfsd4_callback *cb)
{
struct nfs4_layout_stateid *ls =
@@ -661,6 +661,7 @@ nfsd4_cb_layout_prepare(struct nfsd4_callback *cb)
mutex_lock(&ls->ls_mutex);
nfs4_inc_and_copy_stateid(&ls->ls_recall_sid, &ls->ls_stid);
mutex_unlock(&ls->ls_mutex);
+ return true;
}
static int
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index efbc99f0a965..3efc53f0dde6 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -357,12 +357,13 @@ remove_blocked_locks(struct nfs4_lockowner *lo)
}
}
-static void
+static bool
nfsd4_cb_notify_lock_prepare(struct nfsd4_callback *cb)
{
struct nfsd4_blocked_lock *nbl = container_of(cb,
struct nfsd4_blocked_lock, nbl_cb);
locks_delete_block(&nbl->nbl_lock);
+ return true;
}
static int
@@ -5562,7 +5563,7 @@ bool nfsd_wait_for_delegreturn(struct svc_rqst *rqstp, struct inode *inode)
return timeo > 0;
}
-static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb)
+static bool nfsd4_cb_recall_prepare(struct nfsd4_callback *cb)
{
struct nfs4_delegation *dp = cb_to_delegation(cb);
struct nfsd_net *nn = net_generic(dp->dl_stid.sc_client->net,
@@ -5583,6 +5584,7 @@ static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb)
list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru);
}
spin_unlock(&nn->deleg_lock);
+ return true;
}
static int nfsd4_cb_recall_done(struct nfsd4_callback *cb,
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index dec83e92650d..e1c40f8b5d01 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -98,9 +98,9 @@ struct nfsd4_callback {
};
struct nfsd4_callback_ops {
- void (*prepare)(struct nfsd4_callback *);
- int (*done)(struct nfsd4_callback *, struct rpc_task *);
- void (*release)(struct nfsd4_callback *);
+ bool (*prepare)(struct nfsd4_callback *cb);
+ int (*done)(struct nfsd4_callback *cb, struct rpc_task *task);
+ void (*release)(struct nfsd4_callback *cb);
uint32_t opcode;
};
--
2.54.0
^ permalink raw reply related
* [PATCH v5 05/21] nfsd: update the fsnotify mark when setting or removing a dir delegation
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
In-Reply-To: <20260522-dir-deleg-v5-0-542cddfad576@kernel.org>
Add a new helper function that will update the mask on the nfsd_file's
fsnotify_mark to be a union of all current directory delegations on an
inode. Call that when directory delegations are added or removed.
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4state.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 2a34ba457b74..efbc99f0a965 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1246,6 +1246,38 @@ static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct f
nfsd_update_cmtime_attr(f, ATTR_ATIME);
}
+static void nfsd_fsnotify_recalc_mask(struct nfsd_file *nf)
+{
+ struct inode *inode = file_inode(nf->nf_file);
+ u32 lease_mask, set = 0, clear = 0;
+ struct fsnotify_mark *mark;
+
+ /* This is only needed when adding or removing dir delegs */
+ if (!S_ISDIR(inode->i_mode) || !nf->nf_mark)
+ return;
+
+ /* Set up notifications for any ignored delegation events */
+ lease_mask = inode_lease_ignore_mask(inode);
+ mark = &nf->nf_mark->nfm_mark;
+
+ if (lease_mask & FL_IGN_DIR_CREATE)
+ set |= FS_CREATE | FS_MOVED_TO;
+ else
+ clear |= FS_CREATE | FS_MOVED_TO;
+
+ if (lease_mask & FL_IGN_DIR_DELETE)
+ set |= FS_DELETE | FS_MOVED_FROM;
+ else
+ clear |= FS_DELETE | FS_MOVED_FROM;
+
+ if (lease_mask & FL_IGN_DIR_RENAME)
+ set |= FS_RENAME;
+ else
+ clear |= FS_RENAME;
+
+ fsnotify_modify_mark_mask(mark, set, clear);
+}
+
static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
{
struct nfs4_file *fp = dp->dl_stid.sc_file;
@@ -1255,6 +1287,7 @@ static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
nfsd4_finalize_deleg_timestamps(dp, nf->nf_file);
kernel_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp);
+ nfsd_fsnotify_recalc_mask(nf);
put_deleg_file(fp);
}
@@ -9682,6 +9715,7 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate,
if (!status) {
put_nfs4_file(fp);
+ nfsd_fsnotify_recalc_mask(nf);
return dp;
}
--
2.54.0
^ permalink raw reply related
* [PATCH v5 04/21] nfsd: allow nfsd to get a dir lease with an ignore mask
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
In-Reply-To: <20260522-dir-deleg-v5-0-542cddfad576@kernel.org>
When requesting a directory lease, enable the FL_IGN_DIR_* bits that
correspond to the requested notification types.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4state.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 67e163ee13a2..2a34ba457b74 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -6048,7 +6048,22 @@ static bool nfsd4_cb_channel_good(struct nfs4_client *clp)
return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN;
}
-static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp)
+static unsigned int
+nfsd_notify_to_ignore(u32 notify)
+{
+ unsigned int mask = 0;
+
+ if (notify & BIT(NOTIFY4_REMOVE_ENTRY))
+ mask |= FL_IGN_DIR_DELETE;
+ if (notify & BIT(NOTIFY4_ADD_ENTRY))
+ mask |= FL_IGN_DIR_CREATE;
+ if (notify & BIT(NOTIFY4_RENAME_ENTRY))
+ mask |= FL_IGN_DIR_RENAME;
+
+ return mask;
+}
+
+static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp, u32 notify)
{
struct file_lease *fl;
@@ -6056,7 +6071,7 @@ static struct file_lease *nfs4_alloc_init_lease(struct nfs4_delegation *dp)
if (!fl)
return NULL;
fl->fl_lmops = &nfsd_lease_mng_ops;
- fl->c.flc_flags = FL_DELEG;
+ fl->c.flc_flags = FL_DELEG | nfsd_notify_to_ignore(notify);
fl->c.flc_type = deleg_is_read(dp->dl_type) ? F_RDLCK : F_WRLCK;
fl->c.flc_owner = (fl_owner_t)dp;
fl->c.flc_pid = current->tgid;
@@ -6273,7 +6288,7 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
if (stp->st_stid.sc_export)
dp->dl_stid.sc_export = exp_get(stp->st_stid.sc_export);
- fl = nfs4_alloc_init_lease(dp);
+ fl = nfs4_alloc_init_lease(dp, 0);
if (!fl)
goto out_clnt_odstate;
@@ -9642,12 +9657,11 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate,
dp->dl_stid.sc_export =
exp_get(cstate->current_fh.fh_export);
- fl = nfs4_alloc_init_lease(dp);
+ fl = nfs4_alloc_init_lease(dp, gdd->gddr_notification[0]);
if (!fl)
goto out_put_stid;
- status = kernel_setlease(nf->nf_file,
- fl->c.flc_type, &fl, NULL);
+ status = kernel_setlease(nf->nf_file, fl->c.flc_type, &fl, NULL);
if (fl)
locks_free_lease(fl);
if (status)
--
2.54.0
^ permalink raw reply related
* [PATCH v5 03/21] nfs_common: add new NOTIFY4_* flags proposed in RFC8881bis
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
In-Reply-To: <20260522-dir-deleg-v5-0-542cddfad576@kernel.org>
RFC8881bis adds some new flags to GET_DIR_DELEGATION that we very much
need to support.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
Documentation/sunrpc/xdr/nfs4_1.x | 16 +++++++++++++++-
fs/nfsd/nfs4xdr_gen.c | 13 ++++++++++++-
fs/nfsd/nfs4xdr_gen.h | 2 +-
include/linux/sunrpc/xdrgen/nfs4_1.h | 13 ++++++++++++-
4 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/Documentation/sunrpc/xdr/nfs4_1.x b/Documentation/sunrpc/xdr/nfs4_1.x
index 632f5b579c39..aa14b590b524 100644
--- a/Documentation/sunrpc/xdr/nfs4_1.x
+++ b/Documentation/sunrpc/xdr/nfs4_1.x
@@ -416,7 +416,21 @@ enum notify_type4 {
NOTIFY4_REMOVE_ENTRY = 2,
NOTIFY4_ADD_ENTRY = 3,
NOTIFY4_RENAME_ENTRY = 4,
- NOTIFY4_CHANGE_COOKIE_VERIFIER = 5
+ NOTIFY4_CHANGE_COOKIE_VERIFIER = 5,
+ /*
+ * Added in NFSv4.1 bis document
+ */
+ NOTIFY4_GFLAG_EXTEND = 6,
+ NOTIFY4_AUFLAG_VALID = 7,
+ NOTIFY4_AUFLAG_USER = 8,
+ NOTIFY4_AUFLAG_GROUP = 9,
+ NOTIFY4_AUFLAG_OTHER = 10,
+ NOTIFY4_CHANGE_AUTH = 11,
+ NOTIFY4_CFLAG_ORDER = 12,
+ NOTIFY4_AUFLAG_GANOW = 13,
+ NOTIFY4_AUFLAG_GALATER = 14,
+ NOTIFY4_CHANGE_GA = 15,
+ NOTIFY4_CHANGE_AMASK = 16
};
/* Changed entry information. */
diff --git a/fs/nfsd/nfs4xdr_gen.c b/fs/nfsd/nfs4xdr_gen.c
index 5e656d6bbb8e..80369139ef7e 100644
--- a/fs/nfsd/nfs4xdr_gen.c
+++ b/fs/nfsd/nfs4xdr_gen.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// Generated by xdrgen. Manual edits will be lost.
// XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x
-// XDR specification modification time: Wed Mar 25 11:39:22 2026
+// XDR specification modification time: Wed Mar 25 11:40:02 2026
#include <linux/sunrpc/svc.h>
@@ -590,6 +590,17 @@ xdrgen_decode_notify_type4(struct xdr_stream *xdr, notify_type4 *ptr)
case NOTIFY4_ADD_ENTRY:
case NOTIFY4_RENAME_ENTRY:
case NOTIFY4_CHANGE_COOKIE_VERIFIER:
+ case NOTIFY4_GFLAG_EXTEND:
+ case NOTIFY4_AUFLAG_VALID:
+ case NOTIFY4_AUFLAG_USER:
+ case NOTIFY4_AUFLAG_GROUP:
+ case NOTIFY4_AUFLAG_OTHER:
+ case NOTIFY4_CHANGE_AUTH:
+ case NOTIFY4_CFLAG_ORDER:
+ case NOTIFY4_AUFLAG_GANOW:
+ case NOTIFY4_AUFLAG_GALATER:
+ case NOTIFY4_CHANGE_GA:
+ case NOTIFY4_CHANGE_AMASK:
break;
default:
return false;
diff --git a/fs/nfsd/nfs4xdr_gen.h b/fs/nfsd/nfs4xdr_gen.h
index 503fe2ccba51..092a1ed399c7 100644
--- a/fs/nfsd/nfs4xdr_gen.h
+++ b/fs/nfsd/nfs4xdr_gen.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Generated by xdrgen. Manual edits will be lost. */
/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */
-/* XDR specification modification time: Wed Mar 25 11:39:22 2026 */
+/* XDR specification modification time: Wed Mar 25 11:40:02 2026 */
#ifndef _LINUX_XDRGEN_NFS4_1_DECL_H
#define _LINUX_XDRGEN_NFS4_1_DECL_H
diff --git a/include/linux/sunrpc/xdrgen/nfs4_1.h b/include/linux/sunrpc/xdrgen/nfs4_1.h
index f761c3ddb4c7..537504069f24 100644
--- a/include/linux/sunrpc/xdrgen/nfs4_1.h
+++ b/include/linux/sunrpc/xdrgen/nfs4_1.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Generated by xdrgen. Manual edits will be lost. */
/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */
-/* XDR specification modification time: Wed Mar 25 11:39:22 2026 */
+/* XDR specification modification time: Wed Mar 25 11:40:02 2026 */
#ifndef _LINUX_XDRGEN_NFS4_1_DEF_H
#define _LINUX_XDRGEN_NFS4_1_DEF_H
@@ -377,6 +377,17 @@ enum notify_type4 {
NOTIFY4_ADD_ENTRY = 3,
NOTIFY4_RENAME_ENTRY = 4,
NOTIFY4_CHANGE_COOKIE_VERIFIER = 5,
+ NOTIFY4_GFLAG_EXTEND = 6,
+ NOTIFY4_AUFLAG_VALID = 7,
+ NOTIFY4_AUFLAG_USER = 8,
+ NOTIFY4_AUFLAG_GROUP = 9,
+ NOTIFY4_AUFLAG_OTHER = 10,
+ NOTIFY4_CHANGE_AUTH = 11,
+ NOTIFY4_CFLAG_ORDER = 12,
+ NOTIFY4_AUFLAG_GANOW = 13,
+ NOTIFY4_AUFLAG_GALATER = 14,
+ NOTIFY4_CHANGE_GA = 15,
+ NOTIFY4_CHANGE_AMASK = 16,
};
typedef enum notify_type4 notify_type4;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 02/21] nfsd: add protocol support for CB_NOTIFY
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
In-Reply-To: <20260522-dir-deleg-v5-0-542cddfad576@kernel.org>
Add the necessary bits to nfs4_1.x and remove the duplicate definitions
from nfs4.h and the uapi nfs4 header. Regenerate the xdr files.
Note that regenerating these files caused conflicts with the definitions
of NFS4_VERIFIER_SIZE and NFS4_FHSIZE in include/uapi/linux/nfs4.h.
These constants are defined by the RFC, and are not part of the kernel
API. They have been removed. Userspace consumers who require those
constants should plan to get them from more authoritative sources.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
Documentation/sunrpc/xdr/nfs4_1.x | 250 ++++++++++++++-
fs/nfsd/nfs4xdr_gen.c | 590 ++++++++++++++++++++++++++++++++++-
fs/nfsd/nfs4xdr_gen.h | 20 +-
fs/nfsd/trace.h | 1 +
include/linux/nfs4.h | 127 --------
include/linux/sunrpc/xdrgen/nfs4_1.h | 280 ++++++++++++++++-
include/uapi/linux/nfs4.h | 2 -
7 files changed, 1129 insertions(+), 141 deletions(-)
diff --git a/Documentation/sunrpc/xdr/nfs4_1.x b/Documentation/sunrpc/xdr/nfs4_1.x
index 5b45547b2ebc..632f5b579c39 100644
--- a/Documentation/sunrpc/xdr/nfs4_1.x
+++ b/Documentation/sunrpc/xdr/nfs4_1.x
@@ -45,19 +45,165 @@ pragma header nfs4;
/*
* Basic typedefs for RFC 1832 data type definitions
*/
-typedef hyper int64_t;
-typedef unsigned int uint32_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef hyper int64_t;
+typedef unsigned hyper uint64_t;
+
+const NFS4_VERIFIER_SIZE = 8;
+const NFS4_FHSIZE = 128;
+
+enum nfsstat4 {
+ NFS4_OK = 0, /* everything is okay */
+ NFS4ERR_PERM = 1, /* caller not privileged */
+ NFS4ERR_NOENT = 2, /* no such file/directory */
+ NFS4ERR_IO = 5, /* hard I/O error */
+ NFS4ERR_NXIO = 6, /* no such device */
+ NFS4ERR_ACCESS = 13, /* access denied */
+ NFS4ERR_EXIST = 17, /* file already exists */
+ NFS4ERR_XDEV = 18, /* different filesystems */
+
+ /*
+ * Please do not allocate value 19; it was used in NFSv3
+ * and we do not want a value in NFSv3 to have a different
+ * meaning in NFSv4.x.
+ */
+
+ NFS4ERR_NOTDIR = 20, /* should be a directory */
+ NFS4ERR_ISDIR = 21, /* should not be directory */
+ NFS4ERR_INVAL = 22, /* invalid argument */
+ NFS4ERR_FBIG = 27, /* file exceeds server max */
+ NFS4ERR_NOSPC = 28, /* no space on filesystem */
+ NFS4ERR_ROFS = 30, /* read-only filesystem */
+ NFS4ERR_MLINK = 31, /* too many hard links */
+ NFS4ERR_NAMETOOLONG = 63, /* name exceeds server max */
+ NFS4ERR_NOTEMPTY = 66, /* directory not empty */
+ NFS4ERR_DQUOT = 69, /* hard quota limit reached*/
+ NFS4ERR_STALE = 70, /* file no longer exists */
+ NFS4ERR_BADHANDLE = 10001,/* Illegal filehandle */
+ NFS4ERR_BAD_COOKIE = 10003,/* READDIR cookie is stale */
+ NFS4ERR_NOTSUPP = 10004,/* operation not supported */
+ NFS4ERR_TOOSMALL = 10005,/* response limit exceeded */
+ NFS4ERR_SERVERFAULT = 10006,/* undefined server error */
+ NFS4ERR_BADTYPE = 10007,/* type invalid for CREATE */
+ NFS4ERR_DELAY = 10008,/* file "busy" - retry */
+ NFS4ERR_SAME = 10009,/* nverify says attrs same */
+ NFS4ERR_DENIED = 10010,/* lock unavailable */
+ NFS4ERR_EXPIRED = 10011,/* lock lease expired */
+ NFS4ERR_LOCKED = 10012,/* I/O failed due to lock */
+ NFS4ERR_GRACE = 10013,/* in grace period */
+ NFS4ERR_FHEXPIRED = 10014,/* filehandle expired */
+ NFS4ERR_SHARE_DENIED = 10015,/* share reserve denied */
+ NFS4ERR_WRONGSEC = 10016,/* wrong security flavor */
+ NFS4ERR_CLID_INUSE = 10017,/* clientid in use */
+
+ /* NFS4ERR_RESOURCE is not a valid error in NFSv4.1 */
+ NFS4ERR_RESOURCE = 10018,/* resource exhaustion */
+
+ NFS4ERR_MOVED = 10019,/* filesystem relocated */
+ NFS4ERR_NOFILEHANDLE = 10020,/* current FH is not set */
+ NFS4ERR_MINOR_VERS_MISMATCH= 10021,/* minor vers not supp */
+ NFS4ERR_STALE_CLIENTID = 10022,/* server has rebooted */
+ NFS4ERR_STALE_STATEID = 10023,/* server has rebooted */
+ NFS4ERR_OLD_STATEID = 10024,/* state is out of sync */
+ NFS4ERR_BAD_STATEID = 10025,/* incorrect stateid */
+ NFS4ERR_BAD_SEQID = 10026,/* request is out of seq. */
+ NFS4ERR_NOT_SAME = 10027,/* verify - attrs not same */
+ NFS4ERR_LOCK_RANGE = 10028,/* overlapping lock range */
+ NFS4ERR_SYMLINK = 10029,/* should be file/directory*/
+ NFS4ERR_RESTOREFH = 10030,/* no saved filehandle */
+ NFS4ERR_LEASE_MOVED = 10031,/* some filesystem moved */
+ NFS4ERR_ATTRNOTSUPP = 10032,/* recommended attr not sup*/
+ NFS4ERR_NO_GRACE = 10033,/* reclaim outside of grace*/
+ NFS4ERR_RECLAIM_BAD = 10034,/* reclaim error at server */
+ NFS4ERR_RECLAIM_CONFLICT= 10035,/* conflict on reclaim */
+ NFS4ERR_BADXDR = 10036,/* XDR decode failed */
+ NFS4ERR_LOCKS_HELD = 10037,/* file locks held at CLOSE*/
+ NFS4ERR_OPENMODE = 10038,/* conflict in OPEN and I/O*/
+ NFS4ERR_BADOWNER = 10039,/* owner translation bad */
+ NFS4ERR_BADCHAR = 10040,/* utf-8 char not supported*/
+ NFS4ERR_BADNAME = 10041,/* name not supported */
+ NFS4ERR_BAD_RANGE = 10042,/* lock range not supported*/
+ NFS4ERR_LOCK_NOTSUPP = 10043,/* no atomic up/downgrade */
+ NFS4ERR_OP_ILLEGAL = 10044,/* undefined operation */
+ NFS4ERR_DEADLOCK = 10045,/* file locking deadlock */
+ NFS4ERR_FILE_OPEN = 10046,/* open file blocks op. */
+ NFS4ERR_ADMIN_REVOKED = 10047,/* lockowner state revoked */
+ NFS4ERR_CB_PATH_DOWN = 10048,/* callback path down */
+
+ /* NFSv4.1 errors start here. */
+
+ NFS4ERR_BADIOMODE = 10049,
+ NFS4ERR_BADLAYOUT = 10050,
+ NFS4ERR_BAD_SESSION_DIGEST = 10051,
+ NFS4ERR_BADSESSION = 10052,
+ NFS4ERR_BADSLOT = 10053,
+ NFS4ERR_COMPLETE_ALREADY = 10054,
+ NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
+ NFS4ERR_DELEG_ALREADY_WANTED = 10056,
+ NFS4ERR_BACK_CHAN_BUSY = 10057,/*backchan reqs outstanding*/
+ NFS4ERR_LAYOUTTRYLATER = 10058,
+ NFS4ERR_LAYOUTUNAVAILABLE = 10059,
+ NFS4ERR_NOMATCHING_LAYOUT = 10060,
+ NFS4ERR_RECALLCONFLICT = 10061,
+ NFS4ERR_UNKNOWN_LAYOUTTYPE = 10062,
+ NFS4ERR_SEQ_MISORDERED = 10063,/* unexpected seq.ID in req*/
+ NFS4ERR_SEQUENCE_POS = 10064,/* [CB_]SEQ. op not 1st op */
+ NFS4ERR_REQ_TOO_BIG = 10065,/* request too big */
+ NFS4ERR_REP_TOO_BIG = 10066,/* reply too big */
+ NFS4ERR_REP_TOO_BIG_TO_CACHE =10067,/* rep. not all cached*/
+ NFS4ERR_RETRY_UNCACHED_REP =10068,/* retry & rep. uncached*/
+ NFS4ERR_UNSAFE_COMPOUND =10069,/* retry/recovery too hard */
+ NFS4ERR_TOO_MANY_OPS = 10070,/*too many ops in [CB_]COMP*/
+ NFS4ERR_OP_NOT_IN_SESSION =10071,/* op needs [CB_]SEQ. op */
+ NFS4ERR_HASH_ALG_UNSUPP = 10072, /* hash alg. not supp. */
+ /* Error 10073 is unused. */
+ NFS4ERR_CLIENTID_BUSY = 10074,/* clientid has state */
+ NFS4ERR_PNFS_IO_HOLE = 10075,/* IO to _SPARSE file hole */
+ NFS4ERR_SEQ_FALSE_RETRY= 10076,/* Retry != original req. */
+ NFS4ERR_BAD_HIGH_SLOT = 10077,/* req has bad highest_slot*/
+ NFS4ERR_DEADSESSION = 10078,/*new req sent to dead sess*/
+ NFS4ERR_ENCR_ALG_UNSUPP= 10079,/* encr alg. not supp. */
+ NFS4ERR_PNFS_NO_LAYOUT = 10080,/* I/O without a layout */
+ NFS4ERR_NOT_ONLY_OP = 10081,/* addl ops not allowed */
+ NFS4ERR_WRONG_CRED = 10082,/* op done by wrong cred */
+ NFS4ERR_WRONG_TYPE = 10083,/* op on wrong type object */
+ NFS4ERR_DIRDELEG_UNAVAIL=10084,/* delegation not avail. */
+ NFS4ERR_REJECT_DELEG = 10085,/* cb rejected delegation */
+ NFS4ERR_RETURNCONFLICT = 10086,/* layout get before return*/
+ NFS4ERR_DELEG_REVOKED = 10087, /* deleg./layout revoked */
+ NFS4ERR_PARTNER_NOTSUPP = 10088,
+ NFS4ERR_PARTNER_NO_AUTH = 10089,
+ NFS4ERR_UNION_NOTSUPP = 10090,
+ NFS4ERR_OFFLOAD_DENIED = 10091,
+ NFS4ERR_WRONG_LFS = 10092,
+ NFS4ERR_BADLABEL = 10093,
+ NFS4ERR_OFFLOAD_NO_REQS = 10094,
+ NFS4ERR_NOXATTR = 10095,
+ NFS4ERR_XATTR2BIG = 10096,
+
+ /* always set this to one more than the last one in the enum */
+ NFS4ERR_FIRST_FREE = 10097
+};
/*
* Basic data types
*/
+typedef opaque attrlist4<>;
typedef uint32_t bitmap4<>;
+typedef opaque verifier4[NFS4_VERIFIER_SIZE];
+typedef uint64_t nfs_cookie4;
+typedef opaque nfs_fh4<NFS4_FHSIZE>;
typedef opaque utf8string<>;
typedef utf8string utf8str_cis;
typedef utf8string utf8str_cs;
typedef utf8string utf8str_mixed;
+typedef utf8str_cs component4;
+typedef utf8str_cs linktext4;
+typedef component4 pathname4<>;
+
/*
* Timeval
*/
@@ -66,6 +212,21 @@ struct nfstime4 {
uint32_t nseconds;
};
+/*
+ * File attribute container
+ */
+struct fattr4 {
+ bitmap4 attrmask;
+ attrlist4 attr_vals;
+};
+
+/*
+ * Stateid
+ */
+struct stateid4 {
+ uint32_t seqid;
+ opaque other[12];
+};
/*
* The following content was extracted from draft-ietf-nfsv4-delstid
@@ -245,3 +406,88 @@ const FATTR4_ACL_TRUEFORM = 89;
const FATTR4_ACL_TRUEFORM_SCOPE = 90;
const FATTR4_POSIX_DEFAULT_ACL = 91;
const FATTR4_POSIX_ACCESS_ACL = 92;
+
+/*
+ * Directory notification types.
+ */
+enum notify_type4 {
+ NOTIFY4_CHANGE_CHILD_ATTRS = 0,
+ NOTIFY4_CHANGE_DIR_ATTRS = 1,
+ NOTIFY4_REMOVE_ENTRY = 2,
+ NOTIFY4_ADD_ENTRY = 3,
+ NOTIFY4_RENAME_ENTRY = 4,
+ NOTIFY4_CHANGE_COOKIE_VERIFIER = 5
+};
+
+/* Changed entry information. */
+struct notify_entry4 {
+ component4 ne_file;
+ fattr4 ne_attrs;
+};
+
+/* Previous entry information */
+struct prev_entry4 {
+ notify_entry4 pe_prev_entry;
+ /* what READDIR returned for this entry */
+ nfs_cookie4 pe_prev_entry_cookie;
+};
+
+struct notify_remove4 {
+ notify_entry4 nrm_old_entry;
+ nfs_cookie4 nrm_old_entry_cookie;
+};
+pragma public notify_remove4;
+
+struct notify_add4 {
+ /*
+ * Information on object
+ * possibly renamed over.
+ */
+ notify_remove4 nad_old_entry<1>;
+ notify_entry4 nad_new_entry;
+ /* what READDIR would have returned for this entry */
+ nfs_cookie4 nad_new_entry_cookie<1>;
+ prev_entry4 nad_prev_entry<1>;
+ bool nad_last_entry;
+};
+pragma public notify_add4;
+
+struct notify_attr4 {
+ notify_entry4 na_changed_entry;
+};
+pragma public notify_attr4;
+
+struct notify_rename4 {
+ notify_remove4 nrn_old_entry;
+ notify_add4 nrn_new_entry;
+};
+pragma public notify_rename4;
+
+struct notify_verifier4 {
+ verifier4 nv_old_cookieverf;
+ verifier4 nv_new_cookieverf;
+};
+
+/*
+ * Objects of type notify_<>4 and
+ * notify_device_<>4 are encoded in this.
+ */
+typedef opaque notifylist4<>;
+
+struct notify4 {
+ /* composed from notify_type4 or notify_deviceid_type4 */
+ bitmap4 notify_mask;
+ notifylist4 notify_vals;
+};
+
+struct CB_NOTIFY4args {
+ stateid4 cna_stateid;
+ nfs_fh4 cna_fh;
+ notify4 cna_changes<>;
+};
+pragma public CB_NOTIFY4args;
+
+struct CB_NOTIFY4res {
+ nfsstat4 cnr_status;
+};
+pragma public CB_NOTIFY4res;
diff --git a/fs/nfsd/nfs4xdr_gen.c b/fs/nfsd/nfs4xdr_gen.c
index 824497051b87..5e656d6bbb8e 100644
--- a/fs/nfsd/nfs4xdr_gen.c
+++ b/fs/nfsd/nfs4xdr_gen.c
@@ -1,16 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
// Generated by xdrgen. Manual edits will be lost.
// XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x
-// XDR specification modification time: Thu Jan 8 23:12:07 2026
+// XDR specification modification time: Wed Mar 25 11:39:22 2026
#include <linux/sunrpc/svc.h>
#include "nfs4xdr_gen.h"
static bool __maybe_unused
-xdrgen_decode_int64_t(struct xdr_stream *xdr, int64_t *ptr)
+xdrgen_decode_int32_t(struct xdr_stream *xdr, int32_t *ptr)
{
- return xdrgen_decode_hyper(xdr, ptr);
+ return xdrgen_decode_int(xdr, ptr);
}
static bool __maybe_unused
@@ -19,6 +19,155 @@ xdrgen_decode_uint32_t(struct xdr_stream *xdr, uint32_t *ptr)
return xdrgen_decode_unsigned_int(xdr, ptr);
}
+static bool __maybe_unused
+xdrgen_decode_int64_t(struct xdr_stream *xdr, int64_t *ptr)
+{
+ return xdrgen_decode_hyper(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_uint64_t(struct xdr_stream *xdr, uint64_t *ptr)
+{
+ return xdrgen_decode_unsigned_hyper(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_nfsstat4(struct xdr_stream *xdr, nfsstat4 *ptr)
+{
+ u32 val;
+
+ if (xdr_stream_decode_u32(xdr, &val) < 0)
+ return false;
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case NFS4_OK:
+ case NFS4ERR_PERM:
+ case NFS4ERR_NOENT:
+ case NFS4ERR_IO:
+ case NFS4ERR_NXIO:
+ case NFS4ERR_ACCESS:
+ case NFS4ERR_EXIST:
+ case NFS4ERR_XDEV:
+ case NFS4ERR_NOTDIR:
+ case NFS4ERR_ISDIR:
+ case NFS4ERR_INVAL:
+ case NFS4ERR_FBIG:
+ case NFS4ERR_NOSPC:
+ case NFS4ERR_ROFS:
+ case NFS4ERR_MLINK:
+ case NFS4ERR_NAMETOOLONG:
+ case NFS4ERR_NOTEMPTY:
+ case NFS4ERR_DQUOT:
+ case NFS4ERR_STALE:
+ case NFS4ERR_BADHANDLE:
+ case NFS4ERR_BAD_COOKIE:
+ case NFS4ERR_NOTSUPP:
+ case NFS4ERR_TOOSMALL:
+ case NFS4ERR_SERVERFAULT:
+ case NFS4ERR_BADTYPE:
+ case NFS4ERR_DELAY:
+ case NFS4ERR_SAME:
+ case NFS4ERR_DENIED:
+ case NFS4ERR_EXPIRED:
+ case NFS4ERR_LOCKED:
+ case NFS4ERR_GRACE:
+ case NFS4ERR_FHEXPIRED:
+ case NFS4ERR_SHARE_DENIED:
+ case NFS4ERR_WRONGSEC:
+ case NFS4ERR_CLID_INUSE:
+ case NFS4ERR_RESOURCE:
+ case NFS4ERR_MOVED:
+ case NFS4ERR_NOFILEHANDLE:
+ case NFS4ERR_MINOR_VERS_MISMATCH:
+ case NFS4ERR_STALE_CLIENTID:
+ case NFS4ERR_STALE_STATEID:
+ case NFS4ERR_OLD_STATEID:
+ case NFS4ERR_BAD_STATEID:
+ case NFS4ERR_BAD_SEQID:
+ case NFS4ERR_NOT_SAME:
+ case NFS4ERR_LOCK_RANGE:
+ case NFS4ERR_SYMLINK:
+ case NFS4ERR_RESTOREFH:
+ case NFS4ERR_LEASE_MOVED:
+ case NFS4ERR_ATTRNOTSUPP:
+ case NFS4ERR_NO_GRACE:
+ case NFS4ERR_RECLAIM_BAD:
+ case NFS4ERR_RECLAIM_CONFLICT:
+ case NFS4ERR_BADXDR:
+ case NFS4ERR_LOCKS_HELD:
+ case NFS4ERR_OPENMODE:
+ case NFS4ERR_BADOWNER:
+ case NFS4ERR_BADCHAR:
+ case NFS4ERR_BADNAME:
+ case NFS4ERR_BAD_RANGE:
+ case NFS4ERR_LOCK_NOTSUPP:
+ case NFS4ERR_OP_ILLEGAL:
+ case NFS4ERR_DEADLOCK:
+ case NFS4ERR_FILE_OPEN:
+ case NFS4ERR_ADMIN_REVOKED:
+ case NFS4ERR_CB_PATH_DOWN:
+ case NFS4ERR_BADIOMODE:
+ case NFS4ERR_BADLAYOUT:
+ case NFS4ERR_BAD_SESSION_DIGEST:
+ case NFS4ERR_BADSESSION:
+ case NFS4ERR_BADSLOT:
+ case NFS4ERR_COMPLETE_ALREADY:
+ case NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case NFS4ERR_DELEG_ALREADY_WANTED:
+ case NFS4ERR_BACK_CHAN_BUSY:
+ case NFS4ERR_LAYOUTTRYLATER:
+ case NFS4ERR_LAYOUTUNAVAILABLE:
+ case NFS4ERR_NOMATCHING_LAYOUT:
+ case NFS4ERR_RECALLCONFLICT:
+ case NFS4ERR_UNKNOWN_LAYOUTTYPE:
+ case NFS4ERR_SEQ_MISORDERED:
+ case NFS4ERR_SEQUENCE_POS:
+ case NFS4ERR_REQ_TOO_BIG:
+ case NFS4ERR_REP_TOO_BIG:
+ case NFS4ERR_REP_TOO_BIG_TO_CACHE:
+ case NFS4ERR_RETRY_UNCACHED_REP:
+ case NFS4ERR_UNSAFE_COMPOUND:
+ case NFS4ERR_TOO_MANY_OPS:
+ case NFS4ERR_OP_NOT_IN_SESSION:
+ case NFS4ERR_HASH_ALG_UNSUPP:
+ case NFS4ERR_CLIENTID_BUSY:
+ case NFS4ERR_PNFS_IO_HOLE:
+ case NFS4ERR_SEQ_FALSE_RETRY:
+ case NFS4ERR_BAD_HIGH_SLOT:
+ case NFS4ERR_DEADSESSION:
+ case NFS4ERR_ENCR_ALG_UNSUPP:
+ case NFS4ERR_PNFS_NO_LAYOUT:
+ case NFS4ERR_NOT_ONLY_OP:
+ case NFS4ERR_WRONG_CRED:
+ case NFS4ERR_WRONG_TYPE:
+ case NFS4ERR_DIRDELEG_UNAVAIL:
+ case NFS4ERR_REJECT_DELEG:
+ case NFS4ERR_RETURNCONFLICT:
+ case NFS4ERR_DELEG_REVOKED:
+ case NFS4ERR_PARTNER_NOTSUPP:
+ case NFS4ERR_PARTNER_NO_AUTH:
+ case NFS4ERR_UNION_NOTSUPP:
+ case NFS4ERR_OFFLOAD_DENIED:
+ case NFS4ERR_WRONG_LFS:
+ case NFS4ERR_BADLABEL:
+ case NFS4ERR_OFFLOAD_NO_REQS:
+ case NFS4ERR_NOXATTR:
+ case NFS4ERR_XATTR2BIG:
+ case NFS4ERR_FIRST_FREE:
+ break;
+ default:
+ return false;
+ }
+ *ptr = val;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_attrlist4(struct xdr_stream *xdr, attrlist4 *ptr)
+{
+ return xdrgen_decode_opaque(xdr, ptr, 0);
+}
+
static bool __maybe_unused
xdrgen_decode_bitmap4(struct xdr_stream *xdr, bitmap4 *ptr)
{
@@ -30,6 +179,24 @@ xdrgen_decode_bitmap4(struct xdr_stream *xdr, bitmap4 *ptr)
return true;
}
+static bool __maybe_unused
+xdrgen_decode_verifier4(struct xdr_stream *xdr, verifier4 *ptr)
+{
+ return xdr_stream_decode_opaque_fixed(xdr, ptr, NFS4_VERIFIER_SIZE) == 0;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nfs_cookie4(struct xdr_stream *xdr, nfs_cookie4 *ptr)
+{
+ return xdrgen_decode_uint64_t(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_nfs_fh4(struct xdr_stream *xdr, nfs_fh4 *ptr)
+{
+ return xdrgen_decode_opaque(xdr, ptr, NFS4_FHSIZE);
+}
+
static bool __maybe_unused
xdrgen_decode_utf8string(struct xdr_stream *xdr, utf8string *ptr)
{
@@ -54,6 +221,29 @@ xdrgen_decode_utf8str_mixed(struct xdr_stream *xdr, utf8str_mixed *ptr)
return xdrgen_decode_utf8string(xdr, ptr);
}
+static bool __maybe_unused
+xdrgen_decode_component4(struct xdr_stream *xdr, component4 *ptr)
+{
+ return xdrgen_decode_utf8str_cs(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_linktext4(struct xdr_stream *xdr, linktext4 *ptr)
+{
+ return xdrgen_decode_utf8str_cs(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_pathname4(struct xdr_stream *xdr, pathname4 *ptr)
+{
+ if (xdr_stream_decode_u32(xdr, &ptr->count) < 0)
+ return false;
+ for (u32 i = 0; i < ptr->count; i++)
+ if (!xdrgen_decode_component4(xdr, &ptr->element[i]))
+ return false;
+ return true;
+}
+
static bool __maybe_unused
xdrgen_decode_nfstime4(struct xdr_stream *xdr, struct nfstime4 *ptr)
{
@@ -64,6 +254,26 @@ xdrgen_decode_nfstime4(struct xdr_stream *xdr, struct nfstime4 *ptr)
return true;
}
+static bool __maybe_unused
+xdrgen_decode_fattr4(struct xdr_stream *xdr, struct fattr4 *ptr)
+{
+ if (!xdrgen_decode_bitmap4(xdr, &ptr->attrmask))
+ return false;
+ if (!xdrgen_decode_attrlist4(xdr, &ptr->attr_vals))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_stateid4(struct xdr_stream *xdr, struct stateid4 *ptr)
+{
+ if (!xdrgen_decode_uint32_t(xdr, &ptr->seqid))
+ return false;
+ if (xdr_stream_decode_opaque_fixed(xdr, ptr->other, 12) < 0)
+ return false;
+ return true;
+}
+
static bool __maybe_unused
xdrgen_decode_fattr4_offline(struct xdr_stream *xdr, fattr4_offline *ptr)
{
@@ -366,9 +576,160 @@ xdrgen_decode_fattr4_posix_access_acl(struct xdr_stream *xdr, fattr4_posix_acces
*/
static bool __maybe_unused
-xdrgen_encode_int64_t(struct xdr_stream *xdr, const int64_t value)
+xdrgen_decode_notify_type4(struct xdr_stream *xdr, notify_type4 *ptr)
{
- return xdrgen_encode_hyper(xdr, value);
+ u32 val;
+
+ if (xdr_stream_decode_u32(xdr, &val) < 0)
+ return false;
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case NOTIFY4_CHANGE_CHILD_ATTRS:
+ case NOTIFY4_CHANGE_DIR_ATTRS:
+ case NOTIFY4_REMOVE_ENTRY:
+ case NOTIFY4_ADD_ENTRY:
+ case NOTIFY4_RENAME_ENTRY:
+ case NOTIFY4_CHANGE_COOKIE_VERIFIER:
+ break;
+ default:
+ return false;
+ }
+ *ptr = val;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify_entry4(struct xdr_stream *xdr, struct notify_entry4 *ptr)
+{
+ if (!xdrgen_decode_component4(xdr, &ptr->ne_file))
+ return false;
+ if (!xdrgen_decode_fattr4(xdr, &ptr->ne_attrs))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_prev_entry4(struct xdr_stream *xdr, struct prev_entry4 *ptr)
+{
+ if (!xdrgen_decode_notify_entry4(xdr, &ptr->pe_prev_entry))
+ return false;
+ if (!xdrgen_decode_nfs_cookie4(xdr, &ptr->pe_prev_entry_cookie))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_decode_notify_remove4(struct xdr_stream *xdr, struct notify_remove4 *ptr)
+{
+ if (!xdrgen_decode_notify_entry4(xdr, &ptr->nrm_old_entry))
+ return false;
+ if (!xdrgen_decode_nfs_cookie4(xdr, &ptr->nrm_old_entry_cookie))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_decode_notify_add4(struct xdr_stream *xdr, struct notify_add4 *ptr)
+{
+ if (xdr_stream_decode_u32(xdr, &ptr->nad_old_entry.count) < 0)
+ return false;
+ if (ptr->nad_old_entry.count > 1)
+ return false;
+ for (u32 i = 0; i < ptr->nad_old_entry.count; i++)
+ if (!xdrgen_decode_notify_remove4(xdr, &ptr->nad_old_entry.element[i]))
+ return false;
+ if (!xdrgen_decode_notify_entry4(xdr, &ptr->nad_new_entry))
+ return false;
+ if (xdr_stream_decode_u32(xdr, &ptr->nad_new_entry_cookie.count) < 0)
+ return false;
+ if (ptr->nad_new_entry_cookie.count > 1)
+ return false;
+ for (u32 i = 0; i < ptr->nad_new_entry_cookie.count; i++)
+ if (!xdrgen_decode_nfs_cookie4(xdr, &ptr->nad_new_entry_cookie.element[i]))
+ return false;
+ if (xdr_stream_decode_u32(xdr, &ptr->nad_prev_entry.count) < 0)
+ return false;
+ if (ptr->nad_prev_entry.count > 1)
+ return false;
+ for (u32 i = 0; i < ptr->nad_prev_entry.count; i++)
+ if (!xdrgen_decode_prev_entry4(xdr, &ptr->nad_prev_entry.element[i]))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->nad_last_entry))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_decode_notify_attr4(struct xdr_stream *xdr, struct notify_attr4 *ptr)
+{
+ if (!xdrgen_decode_notify_entry4(xdr, &ptr->na_changed_entry))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_decode_notify_rename4(struct xdr_stream *xdr, struct notify_rename4 *ptr)
+{
+ if (!xdrgen_decode_notify_remove4(xdr, &ptr->nrn_old_entry))
+ return false;
+ if (!xdrgen_decode_notify_add4(xdr, &ptr->nrn_new_entry))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify_verifier4(struct xdr_stream *xdr, struct notify_verifier4 *ptr)
+{
+ if (!xdrgen_decode_verifier4(xdr, &ptr->nv_old_cookieverf))
+ return false;
+ if (!xdrgen_decode_verifier4(xdr, &ptr->nv_new_cookieverf))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_notifylist4(struct xdr_stream *xdr, notifylist4 *ptr)
+{
+ return xdrgen_decode_opaque(xdr, ptr, 0);
+}
+
+static bool __maybe_unused
+xdrgen_decode_notify4(struct xdr_stream *xdr, struct notify4 *ptr)
+{
+ if (!xdrgen_decode_bitmap4(xdr, &ptr->notify_mask))
+ return false;
+ if (!xdrgen_decode_notifylist4(xdr, &ptr->notify_vals))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_decode_CB_NOTIFY4args(struct xdr_stream *xdr, struct CB_NOTIFY4args *ptr)
+{
+ if (!xdrgen_decode_stateid4(xdr, &ptr->cna_stateid))
+ return false;
+ if (!xdrgen_decode_nfs_fh4(xdr, &ptr->cna_fh))
+ return false;
+ if (xdr_stream_decode_u32(xdr, &ptr->cna_changes.count) < 0)
+ return false;
+ for (u32 i = 0; i < ptr->cna_changes.count; i++)
+ if (!xdrgen_decode_notify4(xdr, &ptr->cna_changes.element[i]))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_decode_CB_NOTIFY4res(struct xdr_stream *xdr, struct CB_NOTIFY4res *ptr)
+{
+ if (!xdrgen_decode_nfsstat4(xdr, &ptr->cnr_status))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_int32_t(struct xdr_stream *xdr, const int32_t value)
+{
+ return xdrgen_encode_int(xdr, value);
}
static bool __maybe_unused
@@ -377,6 +738,30 @@ xdrgen_encode_uint32_t(struct xdr_stream *xdr, const uint32_t value)
return xdrgen_encode_unsigned_int(xdr, value);
}
+static bool __maybe_unused
+xdrgen_encode_int64_t(struct xdr_stream *xdr, const int64_t value)
+{
+ return xdrgen_encode_hyper(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_uint64_t(struct xdr_stream *xdr, const uint64_t value)
+{
+ return xdrgen_encode_unsigned_hyper(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_nfsstat4(struct xdr_stream *xdr, nfsstat4 value)
+{
+ return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_attrlist4(struct xdr_stream *xdr, const attrlist4 value)
+{
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
+
static bool __maybe_unused
xdrgen_encode_bitmap4(struct xdr_stream *xdr, const bitmap4 value)
{
@@ -388,6 +773,24 @@ xdrgen_encode_bitmap4(struct xdr_stream *xdr, const bitmap4 value)
return true;
}
+static bool __maybe_unused
+xdrgen_encode_verifier4(struct xdr_stream *xdr, const verifier4 value)
+{
+ return xdr_stream_encode_opaque_fixed(xdr, value, NFS4_VERIFIER_SIZE) >= 0;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nfs_cookie4(struct xdr_stream *xdr, const nfs_cookie4 value)
+{
+ return xdrgen_encode_uint64_t(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_nfs_fh4(struct xdr_stream *xdr, const nfs_fh4 value)
+{
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
+
static bool __maybe_unused
xdrgen_encode_utf8string(struct xdr_stream *xdr, const utf8string value)
{
@@ -412,6 +815,29 @@ xdrgen_encode_utf8str_mixed(struct xdr_stream *xdr, const utf8str_mixed value)
return xdrgen_encode_utf8string(xdr, value);
}
+static bool __maybe_unused
+xdrgen_encode_component4(struct xdr_stream *xdr, const component4 value)
+{
+ return xdrgen_encode_utf8str_cs(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_linktext4(struct xdr_stream *xdr, const linktext4 value)
+{
+ return xdrgen_encode_utf8str_cs(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_pathname4(struct xdr_stream *xdr, const pathname4 value)
+{
+ if (xdr_stream_encode_u32(xdr, value.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value.count; i++)
+ if (!xdrgen_encode_component4(xdr, value.element[i]))
+ return false;
+ return true;
+}
+
static bool __maybe_unused
xdrgen_encode_nfstime4(struct xdr_stream *xdr, const struct nfstime4 *value)
{
@@ -422,6 +848,26 @@ xdrgen_encode_nfstime4(struct xdr_stream *xdr, const struct nfstime4 *value)
return true;
}
+static bool __maybe_unused
+xdrgen_encode_fattr4(struct xdr_stream *xdr, const struct fattr4 *value)
+{
+ if (!xdrgen_encode_bitmap4(xdr, value->attrmask))
+ return false;
+ if (!xdrgen_encode_attrlist4(xdr, value->attr_vals))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_stateid4(struct xdr_stream *xdr, const struct stateid4 *value)
+{
+ if (!xdrgen_encode_uint32_t(xdr, value->seqid))
+ return false;
+ if (xdr_stream_encode_opaque_fixed(xdr, value->other, 12) < 0)
+ return false;
+ return true;
+}
+
static bool __maybe_unused
xdrgen_encode_fattr4_offline(struct xdr_stream *xdr, const fattr4_offline value)
{
@@ -567,3 +1013,137 @@ xdrgen_encode_fattr4_posix_access_acl(struct xdr_stream *xdr, const fattr4_posix
return false;
return true;
}
+
+static bool __maybe_unused
+xdrgen_encode_notify_type4(struct xdr_stream *xdr, notify_type4 value)
+{
+ return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify_entry4(struct xdr_stream *xdr, const struct notify_entry4 *value)
+{
+ if (!xdrgen_encode_component4(xdr, value->ne_file))
+ return false;
+ if (!xdrgen_encode_fattr4(xdr, &value->ne_attrs))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_prev_entry4(struct xdr_stream *xdr, const struct prev_entry4 *value)
+{
+ if (!xdrgen_encode_notify_entry4(xdr, &value->pe_prev_entry))
+ return false;
+ if (!xdrgen_encode_nfs_cookie4(xdr, value->pe_prev_entry_cookie))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_encode_notify_remove4(struct xdr_stream *xdr, const struct notify_remove4 *value)
+{
+ if (!xdrgen_encode_notify_entry4(xdr, &value->nrm_old_entry))
+ return false;
+ if (!xdrgen_encode_nfs_cookie4(xdr, value->nrm_old_entry_cookie))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_encode_notify_add4(struct xdr_stream *xdr, const struct notify_add4 *value)
+{
+ if (value->nad_old_entry.count > 1)
+ return false;
+ if (xdr_stream_encode_u32(xdr, value->nad_old_entry.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->nad_old_entry.count; i++)
+ if (!xdrgen_encode_notify_remove4(xdr, &value->nad_old_entry.element[i]))
+ return false;
+ if (!xdrgen_encode_notify_entry4(xdr, &value->nad_new_entry))
+ return false;
+ if (value->nad_new_entry_cookie.count > 1)
+ return false;
+ if (xdr_stream_encode_u32(xdr, value->nad_new_entry_cookie.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->nad_new_entry_cookie.count; i++)
+ if (!xdrgen_encode_nfs_cookie4(xdr, value->nad_new_entry_cookie.element[i]))
+ return false;
+ if (value->nad_prev_entry.count > 1)
+ return false;
+ if (xdr_stream_encode_u32(xdr, value->nad_prev_entry.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->nad_prev_entry.count; i++)
+ if (!xdrgen_encode_prev_entry4(xdr, &value->nad_prev_entry.element[i]))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->nad_last_entry))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_encode_notify_attr4(struct xdr_stream *xdr, const struct notify_attr4 *value)
+{
+ if (!xdrgen_encode_notify_entry4(xdr, &value->na_changed_entry))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_encode_notify_rename4(struct xdr_stream *xdr, const struct notify_rename4 *value)
+{
+ if (!xdrgen_encode_notify_remove4(xdr, &value->nrn_old_entry))
+ return false;
+ if (!xdrgen_encode_notify_add4(xdr, &value->nrn_new_entry))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify_verifier4(struct xdr_stream *xdr, const struct notify_verifier4 *value)
+{
+ if (!xdrgen_encode_verifier4(xdr, value->nv_old_cookieverf))
+ return false;
+ if (!xdrgen_encode_verifier4(xdr, value->nv_new_cookieverf))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notifylist4(struct xdr_stream *xdr, const notifylist4 value)
+{
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
+
+static bool __maybe_unused
+xdrgen_encode_notify4(struct xdr_stream *xdr, const struct notify4 *value)
+{
+ if (!xdrgen_encode_bitmap4(xdr, value->notify_mask))
+ return false;
+ if (!xdrgen_encode_notifylist4(xdr, value->notify_vals))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_encode_CB_NOTIFY4args(struct xdr_stream *xdr, const struct CB_NOTIFY4args *value)
+{
+ if (!xdrgen_encode_stateid4(xdr, &value->cna_stateid))
+ return false;
+ if (!xdrgen_encode_nfs_fh4(xdr, value->cna_fh))
+ return false;
+ if (xdr_stream_encode_u32(xdr, value->cna_changes.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->cna_changes.count; i++)
+ if (!xdrgen_encode_notify4(xdr, &value->cna_changes.element[i]))
+ return false;
+ return true;
+}
+
+bool
+xdrgen_encode_CB_NOTIFY4res(struct xdr_stream *xdr, const struct CB_NOTIFY4res *value)
+{
+ if (!xdrgen_encode_nfsstat4(xdr, value->cnr_status))
+ return false;
+ return true;
+}
diff --git a/fs/nfsd/nfs4xdr_gen.h b/fs/nfsd/nfs4xdr_gen.h
index 1c487f1a11ab..503fe2ccba51 100644
--- a/fs/nfsd/nfs4xdr_gen.h
+++ b/fs/nfsd/nfs4xdr_gen.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Generated by xdrgen. Manual edits will be lost. */
/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */
-/* XDR specification modification time: Thu Jan 8 23:12:07 2026 */
+/* XDR specification modification time: Wed Mar 25 11:39:22 2026 */
#ifndef _LINUX_XDRGEN_NFS4_1_DECL_H
#define _LINUX_XDRGEN_NFS4_1_DECL_H
@@ -32,4 +32,22 @@ bool xdrgen_decode_posixaceperm4(struct xdr_stream *xdr, posixaceperm4 *ptr);
bool xdrgen_encode_posixaceperm4(struct xdr_stream *xdr, const posixaceperm4 value);
+bool xdrgen_decode_notify_remove4(struct xdr_stream *xdr, struct notify_remove4 *ptr);
+bool xdrgen_encode_notify_remove4(struct xdr_stream *xdr, const struct notify_remove4 *value);
+
+bool xdrgen_decode_notify_add4(struct xdr_stream *xdr, struct notify_add4 *ptr);
+bool xdrgen_encode_notify_add4(struct xdr_stream *xdr, const struct notify_add4 *value);
+
+bool xdrgen_decode_notify_attr4(struct xdr_stream *xdr, struct notify_attr4 *ptr);
+bool xdrgen_encode_notify_attr4(struct xdr_stream *xdr, const struct notify_attr4 *value);
+
+bool xdrgen_decode_notify_rename4(struct xdr_stream *xdr, struct notify_rename4 *ptr);
+bool xdrgen_encode_notify_rename4(struct xdr_stream *xdr, const struct notify_rename4 *value);
+
+bool xdrgen_decode_CB_NOTIFY4args(struct xdr_stream *xdr, struct CB_NOTIFY4args *ptr);
+bool xdrgen_encode_CB_NOTIFY4args(struct xdr_stream *xdr, const struct CB_NOTIFY4args *value);
+
+bool xdrgen_decode_CB_NOTIFY4res(struct xdr_stream *xdr, struct CB_NOTIFY4res *ptr);
+bool xdrgen_encode_CB_NOTIFY4res(struct xdr_stream *xdr, const struct CB_NOTIFY4res *value);
+
#endif /* _LINUX_XDRGEN_NFS4_1_DECL_H */
diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
index 1c5a1e50f946..ebf5677c4e73 100644
--- a/fs/nfsd/trace.h
+++ b/fs/nfsd/trace.h
@@ -1677,6 +1677,7 @@ TRACE_EVENT(nfsd_cb_setup_err,
{ OP_CB_RECALL, "CB_RECALL" }, \
{ OP_CB_LAYOUTRECALL, "CB_LAYOUTRECALL" }, \
{ OP_CB_RECALL_ANY, "CB_RECALL_ANY" }, \
+ { OP_CB_NOTIFY, "CB_NOTIFY" }, \
{ OP_CB_NOTIFY_LOCK, "CB_NOTIFY_LOCK" }, \
{ OP_CB_OFFLOAD, "CB_OFFLOAD" })
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index d87be1f25273..44e5e9fa12e1 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -171,133 +171,6 @@ Needs to be updated if more operations are defined in future.*/
#define LAST_NFS42_OP OP_REMOVEXATTR
#define LAST_NFS4_OP LAST_NFS42_OP
-enum nfsstat4 {
- NFS4_OK = 0,
- NFS4ERR_PERM = 1,
- NFS4ERR_NOENT = 2,
- NFS4ERR_IO = 5,
- NFS4ERR_NXIO = 6,
- NFS4ERR_ACCESS = 13,
- NFS4ERR_EXIST = 17,
- NFS4ERR_XDEV = 18,
- /* Unused/reserved 19 */
- NFS4ERR_NOTDIR = 20,
- NFS4ERR_ISDIR = 21,
- NFS4ERR_INVAL = 22,
- NFS4ERR_FBIG = 27,
- NFS4ERR_NOSPC = 28,
- NFS4ERR_ROFS = 30,
- NFS4ERR_MLINK = 31,
- NFS4ERR_NAMETOOLONG = 63,
- NFS4ERR_NOTEMPTY = 66,
- NFS4ERR_DQUOT = 69,
- NFS4ERR_STALE = 70,
- NFS4ERR_BADHANDLE = 10001,
- NFS4ERR_BAD_COOKIE = 10003,
- NFS4ERR_NOTSUPP = 10004,
- NFS4ERR_TOOSMALL = 10005,
- NFS4ERR_SERVERFAULT = 10006,
- NFS4ERR_BADTYPE = 10007,
- NFS4ERR_DELAY = 10008,
- NFS4ERR_SAME = 10009,
- NFS4ERR_DENIED = 10010,
- NFS4ERR_EXPIRED = 10011,
- NFS4ERR_LOCKED = 10012,
- NFS4ERR_GRACE = 10013,
- NFS4ERR_FHEXPIRED = 10014,
- NFS4ERR_SHARE_DENIED = 10015,
- NFS4ERR_WRONGSEC = 10016,
- NFS4ERR_CLID_INUSE = 10017,
- NFS4ERR_RESOURCE = 10018,
- NFS4ERR_MOVED = 10019,
- NFS4ERR_NOFILEHANDLE = 10020,
- NFS4ERR_MINOR_VERS_MISMATCH = 10021,
- NFS4ERR_STALE_CLIENTID = 10022,
- NFS4ERR_STALE_STATEID = 10023,
- NFS4ERR_OLD_STATEID = 10024,
- NFS4ERR_BAD_STATEID = 10025,
- NFS4ERR_BAD_SEQID = 10026,
- NFS4ERR_NOT_SAME = 10027,
- NFS4ERR_LOCK_RANGE = 10028,
- NFS4ERR_SYMLINK = 10029,
- NFS4ERR_RESTOREFH = 10030,
- NFS4ERR_LEASE_MOVED = 10031,
- NFS4ERR_ATTRNOTSUPP = 10032,
- NFS4ERR_NO_GRACE = 10033,
- NFS4ERR_RECLAIM_BAD = 10034,
- NFS4ERR_RECLAIM_CONFLICT = 10035,
- NFS4ERR_BADXDR = 10036,
- NFS4ERR_LOCKS_HELD = 10037,
- NFS4ERR_OPENMODE = 10038,
- NFS4ERR_BADOWNER = 10039,
- NFS4ERR_BADCHAR = 10040,
- NFS4ERR_BADNAME = 10041,
- NFS4ERR_BAD_RANGE = 10042,
- NFS4ERR_LOCK_NOTSUPP = 10043,
- NFS4ERR_OP_ILLEGAL = 10044,
- NFS4ERR_DEADLOCK = 10045,
- NFS4ERR_FILE_OPEN = 10046,
- NFS4ERR_ADMIN_REVOKED = 10047,
- NFS4ERR_CB_PATH_DOWN = 10048,
-
- /* nfs41 */
- NFS4ERR_BADIOMODE = 10049,
- NFS4ERR_BADLAYOUT = 10050,
- NFS4ERR_BAD_SESSION_DIGEST = 10051,
- NFS4ERR_BADSESSION = 10052,
- NFS4ERR_BADSLOT = 10053,
- NFS4ERR_COMPLETE_ALREADY = 10054,
- NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
- NFS4ERR_DELEG_ALREADY_WANTED = 10056,
- NFS4ERR_BACK_CHAN_BUSY = 10057, /* backchan reqs outstanding */
- NFS4ERR_LAYOUTTRYLATER = 10058,
- NFS4ERR_LAYOUTUNAVAILABLE = 10059,
- NFS4ERR_NOMATCHING_LAYOUT = 10060,
- NFS4ERR_RECALLCONFLICT = 10061,
- NFS4ERR_UNKNOWN_LAYOUTTYPE = 10062,
- NFS4ERR_SEQ_MISORDERED = 10063, /* unexpected seq.id in req */
- NFS4ERR_SEQUENCE_POS = 10064, /* [CB_]SEQ. op not 1st op */
- NFS4ERR_REQ_TOO_BIG = 10065, /* request too big */
- NFS4ERR_REP_TOO_BIG = 10066, /* reply too big */
- NFS4ERR_REP_TOO_BIG_TO_CACHE = 10067, /* rep. not all cached */
- NFS4ERR_RETRY_UNCACHED_REP = 10068, /* retry & rep. uncached */
- NFS4ERR_UNSAFE_COMPOUND = 10069, /* retry/recovery too hard */
- NFS4ERR_TOO_MANY_OPS = 10070, /* too many ops in [CB_]COMP */
- NFS4ERR_OP_NOT_IN_SESSION = 10071, /* op needs [CB_]SEQ. op */
- NFS4ERR_HASH_ALG_UNSUPP = 10072, /* hash alg. not supp. */
- /* Error 10073 is unused. */
- NFS4ERR_CLIENTID_BUSY = 10074, /* clientid has state */
- NFS4ERR_PNFS_IO_HOLE = 10075, /* IO to _SPARSE file hole */
- NFS4ERR_SEQ_FALSE_RETRY = 10076, /* retry not original */
- NFS4ERR_BAD_HIGH_SLOT = 10077, /* sequence arg bad */
- NFS4ERR_DEADSESSION = 10078, /* persistent session dead */
- NFS4ERR_ENCR_ALG_UNSUPP = 10079, /* SSV alg mismatch */
- NFS4ERR_PNFS_NO_LAYOUT = 10080, /* direct I/O with no layout */
- NFS4ERR_NOT_ONLY_OP = 10081, /* bad compound */
- NFS4ERR_WRONG_CRED = 10082, /* permissions:state change */
- NFS4ERR_WRONG_TYPE = 10083, /* current operation mismatch */
- NFS4ERR_DIRDELEG_UNAVAIL = 10084, /* no directory delegation */
- NFS4ERR_REJECT_DELEG = 10085, /* on callback */
- NFS4ERR_RETURNCONFLICT = 10086, /* outstanding layoutreturn */
- NFS4ERR_DELEG_REVOKED = 10087, /* deleg./layout revoked */
-
- /* nfs42 */
- NFS4ERR_PARTNER_NOTSUPP = 10088,
- NFS4ERR_PARTNER_NO_AUTH = 10089,
- NFS4ERR_UNION_NOTSUPP = 10090,
- NFS4ERR_OFFLOAD_DENIED = 10091,
- NFS4ERR_WRONG_LFS = 10092,
- NFS4ERR_BADLABEL = 10093,
- NFS4ERR_OFFLOAD_NO_REQS = 10094,
-
- /* xattr (RFC8276) */
- NFS4ERR_NOXATTR = 10095,
- NFS4ERR_XATTR2BIG = 10096,
-
- /* can be used for internal errors */
- NFS4ERR_FIRST_FREE
-};
-
/* error codes for internal client use */
#define NFS4ERR_RESET_TO_MDS 12001
#define NFS4ERR_RESET_TO_PNFS 12002
diff --git a/include/linux/sunrpc/xdrgen/nfs4_1.h b/include/linux/sunrpc/xdrgen/nfs4_1.h
index 4ac54bdbd335..f761c3ddb4c7 100644
--- a/include/linux/sunrpc/xdrgen/nfs4_1.h
+++ b/include/linux/sunrpc/xdrgen/nfs4_1.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Generated by xdrgen. Manual edits will be lost. */
/* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */
-/* XDR specification modification time: Thu Jan 8 23:12:07 2026 */
+/* XDR specification modification time: Wed Mar 25 11:39:22 2026 */
#ifndef _LINUX_XDRGEN_NFS4_1_DEF_H
#define _LINUX_XDRGEN_NFS4_1_DEF_H
@@ -9,15 +9,150 @@
#include <linux/types.h>
#include <linux/sunrpc/xdrgen/_defs.h>
-typedef s64 int64_t;
+typedef s32 int32_t;
typedef u32 uint32_t;
+typedef s64 int64_t;
+
+typedef u64 uint64_t;
+
+enum { NFS4_VERIFIER_SIZE = 8 };
+
+enum { NFS4_FHSIZE = 128 };
+
+enum nfsstat4 {
+ NFS4_OK = 0,
+ NFS4ERR_PERM = 1,
+ NFS4ERR_NOENT = 2,
+ NFS4ERR_IO = 5,
+ NFS4ERR_NXIO = 6,
+ NFS4ERR_ACCESS = 13,
+ NFS4ERR_EXIST = 17,
+ NFS4ERR_XDEV = 18,
+ NFS4ERR_NOTDIR = 20,
+ NFS4ERR_ISDIR = 21,
+ NFS4ERR_INVAL = 22,
+ NFS4ERR_FBIG = 27,
+ NFS4ERR_NOSPC = 28,
+ NFS4ERR_ROFS = 30,
+ NFS4ERR_MLINK = 31,
+ NFS4ERR_NAMETOOLONG = 63,
+ NFS4ERR_NOTEMPTY = 66,
+ NFS4ERR_DQUOT = 69,
+ NFS4ERR_STALE = 70,
+ NFS4ERR_BADHANDLE = 10001,
+ NFS4ERR_BAD_COOKIE = 10003,
+ NFS4ERR_NOTSUPP = 10004,
+ NFS4ERR_TOOSMALL = 10005,
+ NFS4ERR_SERVERFAULT = 10006,
+ NFS4ERR_BADTYPE = 10007,
+ NFS4ERR_DELAY = 10008,
+ NFS4ERR_SAME = 10009,
+ NFS4ERR_DENIED = 10010,
+ NFS4ERR_EXPIRED = 10011,
+ NFS4ERR_LOCKED = 10012,
+ NFS4ERR_GRACE = 10013,
+ NFS4ERR_FHEXPIRED = 10014,
+ NFS4ERR_SHARE_DENIED = 10015,
+ NFS4ERR_WRONGSEC = 10016,
+ NFS4ERR_CLID_INUSE = 10017,
+ NFS4ERR_RESOURCE = 10018,
+ NFS4ERR_MOVED = 10019,
+ NFS4ERR_NOFILEHANDLE = 10020,
+ NFS4ERR_MINOR_VERS_MISMATCH = 10021,
+ NFS4ERR_STALE_CLIENTID = 10022,
+ NFS4ERR_STALE_STATEID = 10023,
+ NFS4ERR_OLD_STATEID = 10024,
+ NFS4ERR_BAD_STATEID = 10025,
+ NFS4ERR_BAD_SEQID = 10026,
+ NFS4ERR_NOT_SAME = 10027,
+ NFS4ERR_LOCK_RANGE = 10028,
+ NFS4ERR_SYMLINK = 10029,
+ NFS4ERR_RESTOREFH = 10030,
+ NFS4ERR_LEASE_MOVED = 10031,
+ NFS4ERR_ATTRNOTSUPP = 10032,
+ NFS4ERR_NO_GRACE = 10033,
+ NFS4ERR_RECLAIM_BAD = 10034,
+ NFS4ERR_RECLAIM_CONFLICT = 10035,
+ NFS4ERR_BADXDR = 10036,
+ NFS4ERR_LOCKS_HELD = 10037,
+ NFS4ERR_OPENMODE = 10038,
+ NFS4ERR_BADOWNER = 10039,
+ NFS4ERR_BADCHAR = 10040,
+ NFS4ERR_BADNAME = 10041,
+ NFS4ERR_BAD_RANGE = 10042,
+ NFS4ERR_LOCK_NOTSUPP = 10043,
+ NFS4ERR_OP_ILLEGAL = 10044,
+ NFS4ERR_DEADLOCK = 10045,
+ NFS4ERR_FILE_OPEN = 10046,
+ NFS4ERR_ADMIN_REVOKED = 10047,
+ NFS4ERR_CB_PATH_DOWN = 10048,
+ NFS4ERR_BADIOMODE = 10049,
+ NFS4ERR_BADLAYOUT = 10050,
+ NFS4ERR_BAD_SESSION_DIGEST = 10051,
+ NFS4ERR_BADSESSION = 10052,
+ NFS4ERR_BADSLOT = 10053,
+ NFS4ERR_COMPLETE_ALREADY = 10054,
+ NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
+ NFS4ERR_DELEG_ALREADY_WANTED = 10056,
+ NFS4ERR_BACK_CHAN_BUSY = 10057,
+ NFS4ERR_LAYOUTTRYLATER = 10058,
+ NFS4ERR_LAYOUTUNAVAILABLE = 10059,
+ NFS4ERR_NOMATCHING_LAYOUT = 10060,
+ NFS4ERR_RECALLCONFLICT = 10061,
+ NFS4ERR_UNKNOWN_LAYOUTTYPE = 10062,
+ NFS4ERR_SEQ_MISORDERED = 10063,
+ NFS4ERR_SEQUENCE_POS = 10064,
+ NFS4ERR_REQ_TOO_BIG = 10065,
+ NFS4ERR_REP_TOO_BIG = 10066,
+ NFS4ERR_REP_TOO_BIG_TO_CACHE = 10067,
+ NFS4ERR_RETRY_UNCACHED_REP = 10068,
+ NFS4ERR_UNSAFE_COMPOUND = 10069,
+ NFS4ERR_TOO_MANY_OPS = 10070,
+ NFS4ERR_OP_NOT_IN_SESSION = 10071,
+ NFS4ERR_HASH_ALG_UNSUPP = 10072,
+ NFS4ERR_CLIENTID_BUSY = 10074,
+ NFS4ERR_PNFS_IO_HOLE = 10075,
+ NFS4ERR_SEQ_FALSE_RETRY = 10076,
+ NFS4ERR_BAD_HIGH_SLOT = 10077,
+ NFS4ERR_DEADSESSION = 10078,
+ NFS4ERR_ENCR_ALG_UNSUPP = 10079,
+ NFS4ERR_PNFS_NO_LAYOUT = 10080,
+ NFS4ERR_NOT_ONLY_OP = 10081,
+ NFS4ERR_WRONG_CRED = 10082,
+ NFS4ERR_WRONG_TYPE = 10083,
+ NFS4ERR_DIRDELEG_UNAVAIL = 10084,
+ NFS4ERR_REJECT_DELEG = 10085,
+ NFS4ERR_RETURNCONFLICT = 10086,
+ NFS4ERR_DELEG_REVOKED = 10087,
+ NFS4ERR_PARTNER_NOTSUPP = 10088,
+ NFS4ERR_PARTNER_NO_AUTH = 10089,
+ NFS4ERR_UNION_NOTSUPP = 10090,
+ NFS4ERR_OFFLOAD_DENIED = 10091,
+ NFS4ERR_WRONG_LFS = 10092,
+ NFS4ERR_BADLABEL = 10093,
+ NFS4ERR_OFFLOAD_NO_REQS = 10094,
+ NFS4ERR_NOXATTR = 10095,
+ NFS4ERR_XATTR2BIG = 10096,
+ NFS4ERR_FIRST_FREE = 10097,
+};
+
+typedef enum nfsstat4 nfsstat4;
+
+typedef opaque attrlist4;
+
typedef struct {
u32 count;
uint32_t *element;
} bitmap4;
+typedef u8 verifier4[NFS4_VERIFIER_SIZE];
+
+typedef uint64_t nfs_cookie4;
+
+typedef opaque nfs_fh4;
+
typedef opaque utf8string;
typedef utf8string utf8str_cis;
@@ -26,11 +161,30 @@ typedef utf8string utf8str_cs;
typedef utf8string utf8str_mixed;
+typedef utf8str_cs component4;
+
+typedef utf8str_cs linktext4;
+
+typedef struct {
+ u32 count;
+ component4 *element;
+} pathname4;
+
struct nfstime4 {
int64_t seconds;
uint32_t nseconds;
};
+struct fattr4 {
+ bitmap4 attrmask;
+ attrlist4 attr_vals;
+};
+
+struct stateid4 {
+ uint32_t seqid;
+ u8 other[12];
+};
+
typedef bool fattr4_offline;
enum { FATTR4_OFFLINE = 83 };
@@ -216,11 +370,98 @@ enum { FATTR4_POSIX_DEFAULT_ACL = 91 };
enum { FATTR4_POSIX_ACCESS_ACL = 92 };
-#define NFS4_int64_t_sz \
- (XDR_hyper)
+enum notify_type4 {
+ NOTIFY4_CHANGE_CHILD_ATTRS = 0,
+ NOTIFY4_CHANGE_DIR_ATTRS = 1,
+ NOTIFY4_REMOVE_ENTRY = 2,
+ NOTIFY4_ADD_ENTRY = 3,
+ NOTIFY4_RENAME_ENTRY = 4,
+ NOTIFY4_CHANGE_COOKIE_VERIFIER = 5,
+};
+
+typedef enum notify_type4 notify_type4;
+
+struct notify_entry4 {
+ component4 ne_file;
+ struct fattr4 ne_attrs;
+};
+
+struct prev_entry4 {
+ struct notify_entry4 pe_prev_entry;
+ nfs_cookie4 pe_prev_entry_cookie;
+};
+
+struct notify_remove4 {
+ struct notify_entry4 nrm_old_entry;
+ nfs_cookie4 nrm_old_entry_cookie;
+};
+
+struct notify_add4 {
+ struct {
+ u32 count;
+ struct notify_remove4 *element;
+ } nad_old_entry;
+ struct notify_entry4 nad_new_entry;
+ struct {
+ u32 count;
+ nfs_cookie4 *element;
+ } nad_new_entry_cookie;
+ struct {
+ u32 count;
+ struct prev_entry4 *element;
+ } nad_prev_entry;
+ bool nad_last_entry;
+};
+
+struct notify_attr4 {
+ struct notify_entry4 na_changed_entry;
+};
+
+struct notify_rename4 {
+ struct notify_remove4 nrn_old_entry;
+ struct notify_add4 nrn_new_entry;
+};
+
+struct notify_verifier4 {
+ verifier4 nv_old_cookieverf;
+ verifier4 nv_new_cookieverf;
+};
+
+typedef opaque notifylist4;
+
+struct notify4 {
+ bitmap4 notify_mask;
+ notifylist4 notify_vals;
+};
+
+struct CB_NOTIFY4args {
+ struct stateid4 cna_stateid;
+ nfs_fh4 cna_fh;
+ struct {
+ u32 count;
+ struct notify4 *element;
+ } cna_changes;
+};
+
+struct CB_NOTIFY4res {
+ nfsstat4 cnr_status;
+};
+
+#define NFS4_int32_t_sz \
+ (XDR_int)
#define NFS4_uint32_t_sz \
(XDR_unsigned_int)
+#define NFS4_int64_t_sz \
+ (XDR_hyper)
+#define NFS4_uint64_t_sz \
+ (XDR_unsigned_hyper)
+#define NFS4_nfsstat4_sz (XDR_int)
+#define NFS4_attrlist4_sz (XDR_unsigned_int)
#define NFS4_bitmap4_sz (XDR_unsigned_int)
+#define NFS4_verifier4_sz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
+#define NFS4_nfs_cookie4_sz \
+ (NFS4_uint64_t_sz)
+#define NFS4_nfs_fh4_sz (XDR_unsigned_int + XDR_QUADLEN(NFS4_FHSIZE))
#define NFS4_utf8string_sz (XDR_unsigned_int)
#define NFS4_utf8str_cis_sz \
(NFS4_utf8string_sz)
@@ -228,8 +469,17 @@ enum { FATTR4_POSIX_ACCESS_ACL = 92 };
(NFS4_utf8string_sz)
#define NFS4_utf8str_mixed_sz \
(NFS4_utf8string_sz)
+#define NFS4_component4_sz \
+ (NFS4_utf8str_cs_sz)
+#define NFS4_linktext4_sz \
+ (NFS4_utf8str_cs_sz)
+#define NFS4_pathname4_sz (XDR_unsigned_int)
#define NFS4_nfstime4_sz \
(NFS4_int64_t_sz + NFS4_uint32_t_sz)
+#define NFS4_fattr4_sz \
+ (NFS4_bitmap4_sz + NFS4_attrlist4_sz)
+#define NFS4_stateid4_sz \
+ (NFS4_uint32_t_sz + XDR_QUADLEN(12))
#define NFS4_fattr4_offline_sz \
(XDR_bool)
#define NFS4_open_arguments4_sz \
@@ -259,5 +509,27 @@ enum { FATTR4_POSIX_ACCESS_ACL = 92 };
(NFS4_aclscope4_sz)
#define NFS4_fattr4_posix_default_acl_sz (XDR_unsigned_int)
#define NFS4_fattr4_posix_access_acl_sz (XDR_unsigned_int)
+#define NFS4_notify_type4_sz (XDR_int)
+#define NFS4_notify_entry4_sz \
+ (NFS4_component4_sz + NFS4_fattr4_sz)
+#define NFS4_prev_entry4_sz \
+ (NFS4_notify_entry4_sz + NFS4_nfs_cookie4_sz)
+#define NFS4_notify_remove4_sz \
+ (NFS4_notify_entry4_sz + NFS4_nfs_cookie4_sz)
+#define NFS4_notify_add4_sz \
+ (XDR_unsigned_int + (1 * (NFS4_notify_remove4_sz)) + NFS4_notify_entry4_sz + XDR_unsigned_int + (1 * (NFS4_nfs_cookie4_sz)) + XDR_unsigned_int + (1 * (NFS4_prev_entry4_sz)) + XDR_bool)
+#define NFS4_notify_attr4_sz \
+ (NFS4_notify_entry4_sz)
+#define NFS4_notify_rename4_sz \
+ (NFS4_notify_remove4_sz + NFS4_notify_add4_sz)
+#define NFS4_notify_verifier4_sz \
+ (NFS4_verifier4_sz + NFS4_verifier4_sz)
+#define NFS4_notifylist4_sz (XDR_unsigned_int)
+#define NFS4_notify4_sz \
+ (NFS4_bitmap4_sz + NFS4_notifylist4_sz)
+#define NFS4_CB_NOTIFY4args_sz \
+ (NFS4_stateid4_sz + NFS4_nfs_fh4_sz + XDR_unsigned_int)
+#define NFS4_CB_NOTIFY4res_sz \
+ (NFS4_nfsstat4_sz)
#endif /* _LINUX_XDRGEN_NFS4_1_DEF_H */
diff --git a/include/uapi/linux/nfs4.h b/include/uapi/linux/nfs4.h
index 4273e0249fcb..289205b53a08 100644
--- a/include/uapi/linux/nfs4.h
+++ b/include/uapi/linux/nfs4.h
@@ -17,11 +17,9 @@
#include <linux/types.h>
#define NFS4_BITMAP_SIZE 3
-#define NFS4_VERIFIER_SIZE 8
#define NFS4_STATEID_SEQID_SIZE 4
#define NFS4_STATEID_OTHER_SIZE 12
#define NFS4_STATEID_SIZE (NFS4_STATEID_SEQID_SIZE + NFS4_STATEID_OTHER_SIZE)
-#define NFS4_FHSIZE 128
#define NFS4_MAXPATHLEN PATH_MAX
#define NFS4_MAXNAMLEN NAME_MAX
#define NFS4_OPAQUE_LIMIT 1024
--
2.54.0
^ permalink raw reply related
* [PATCH v5 01/21] nfsd: check fl_lmops in nfsd_breaker_owns_lease()
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
In-Reply-To: <20260522-dir-deleg-v5-0-542cddfad576@kernel.org>
Any lease created by nfsd will have its fl_lmops set to
nfsd_lease_mng_ops. Do a quick check for that first when testing whether
the lease breaker owns the lease.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4state.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 2cf021b202a6..67e163ee13a2 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -91,6 +91,8 @@ static void _free_cpntf_state_locked(struct nfsd_net *nn, struct nfs4_cpntf_stat
static void nfsd4_file_hash_remove(struct nfs4_file *fi);
static void deleg_reaper(struct nfsd_net *nn);
+static const struct lease_manager_operations nfsd_lease_mng_ops;
+
/* Locking: */
enum nfsd4_st_mutex_lock_subclass {
@@ -5663,6 +5665,10 @@ static bool nfsd_breaker_owns_lease(struct file_lease *fl)
struct svc_rqst *rqst;
struct nfs4_client *clp;
+ /* Only nfsd leases */
+ if (fl->fl_lmops != &nfsd_lease_mng_ops)
+ return false;
+
rqst = nfsd_current_rqst();
if (!nfsd_v4client(rqst))
return false;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 00/21] nfsd: add support for CB_NOTIFY callbacks in directory delegations
From: Jeff Layton @ 2026-05-22 19:42 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Trond Myklebust, Anna Schumaker, Jonathan Corbet, Shuah Khan
Cc: Steven Rostedt, Alexander Aring, Amir Goldstein, Jan Kara,
Alexander Viro, Christian Brauner, Calum Mackay, linux-kernel,
linux-doc, linux-nfs, Jeff Layton
This version of the patchset fixes up some problems that Sashiko flagged
during review.
Original cover letter follows:
---------------------------------8<------------------------------------
This patchset builds on the directory delegation work we did a few
months ago, to add support for CB_NOTIFY callbacks for some events. In
particular, creates, unlinks and renames. The server also sends updated
directory attributes in the notifications. With this support, the client
can register interest in a directory and get notifications about changes
within it without losing its lease.
The series starts with patches to allow the vfs to ignore certain types
of events on directories. nfsd can then request these sorts of
delegations on directories, and then set up inotify watches on the
directory to trigger sending CB_NOTIFY events.
This has mainly been tested with pynfs, with some new testcases that
I'll be posting soon. They seem to work fine with those tests, but I
don't think we'll want to merge these until we have a complete
client-side implementation to test against.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
Changes in v5:
- properly free dir delegation when alloc_pages_bulk() fails
- handle nfsd_file with no mark in nfsd_fsnotify_recalc_mask()
- nfsd_get_dir_deleg() should use stable nf pointer instead of
depending on fi_deleg_file
- use GFP_NOFS in alloc_nfsd_notify_event() since it's called with locks
held
- nfsd_handle_dir_event() tracepoint now handles NULL pointers safely
- Link to v4: https://lore.kernel.org/r/20260522-dir-deleg-v4-0-2acb883ac6bc@kernel.org
Changes in v4:
- Rebase onto Chuck's nfsd-testing branch. Minor contextual fixups.
- Link to v3: https://lore.kernel.org/r/20260428-dir-deleg-v3-0-5a0780ba9def@kernel.org
Changes in v3:
- Fix error handling in alloc_init_dir_deleg()
- Link to v2: https://lore.kernel.org/r/20260416-dir-deleg-v2-0-851426a550f6@kernel.org
Changes in v2:
- Fix __break_lease handling with different lease types on flc_lease list
- Add FSNOTIFY_EVENT_RENAME data type to properly handle cross-directory rename events
- Display fsnotify mask symbolically in tracepoints
- New tracepoint in fsnotify()
- Recalc fsnotify mask after unlocking lease instead of before
- Don't notify client that is making the changes
- After sending CB_NOTIFY, requeue if new events came in while running
- Document removal of NFS4_VERIFIER_SIZE/NFS4_FHSIZE from UAPI headers
- Properly release nfsd_dir_fsnotify_group on server shutdown
- Link to v1: https://lore.kernel.org/r/20260407-dir-deleg-v1-0-aaf68c478abd@kernel.org
---
Jeff Layton (21):
nfsd: check fl_lmops in nfsd_breaker_owns_lease()
nfsd: add protocol support for CB_NOTIFY
nfs_common: add new NOTIFY4_* flags proposed in RFC8881bis
nfsd: allow nfsd to get a dir lease with an ignore mask
nfsd: update the fsnotify mark when setting or removing a dir delegation
nfsd: make nfsd4_callback_ops->prepare operation bool return
nfsd: add callback encoding and decoding linkages for CB_NOTIFY
nfsd: use RCU to protect fi_deleg_file
nfsd: add data structures for handling CB_NOTIFY
nfsd: add notification handlers for dir events
nfsd: add tracepoint to dir_event handler
nfsd: apply the notify mask to the delegation when requested
nfsd: add helper to marshal a fattr4 from completed args
nfsd: allow nfsd4_encode_fattr4_change() to work with no export
nfsd: send basic file attributes in CB_NOTIFY
nfsd: allow encoding a filehandle into fattr4 without a svc_fh
nfsd: add a fi_connectable flag to struct nfs4_file
nfsd: add the filehandle to returned attributes in CB_NOTIFY
nfsd: properly track requested child attributes
nfsd: track requested dir attributes
nfsd: add support to CB_NOTIFY for dir attribute changes
Documentation/sunrpc/xdr/nfs4_1.x | 264 ++++++++++++++-
fs/nfsd/filecache.c | 70 +++-
fs/nfsd/nfs4callback.c | 60 +++-
fs/nfsd/nfs4layouts.c | 5 +-
fs/nfsd/nfs4proc.c | 17 +
fs/nfsd/nfs4state.c | 554 ++++++++++++++++++++++++++++----
fs/nfsd/nfs4xdr.c | 324 +++++++++++++++++--
fs/nfsd/nfs4xdr_gen.c | 601 ++++++++++++++++++++++++++++++++++-
fs/nfsd/nfs4xdr_gen.h | 20 +-
fs/nfsd/state.h | 72 ++++-
fs/nfsd/trace.h | 24 ++
fs/nfsd/xdr4.h | 5 +
fs/nfsd/xdr4cb.h | 12 +
include/linux/nfs4.h | 127 --------
include/linux/sunrpc/xdrgen/nfs4_1.h | 291 ++++++++++++++++-
include/uapi/linux/nfs4.h | 2 -
16 files changed, 2188 insertions(+), 260 deletions(-)
---
base-commit: 33e9ab952a864ae00bce7e47c3e9add1c4b3d3a3
change-id: 20260325-dir-deleg-339066dd1017
Best regards,
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* Re: [PATCH] ARM: zte: clean up zx297520v3 doc. warnings
From: Stefan Dösinger @ 2026-05-22 19:31 UTC (permalink / raw)
To: linux-kernel, Randy Dunlap
Cc: Linus Walleij, Krzysztof Kozlowski, linux-arm-kernel,
Jonathan Corbet, Shuah Khan, linux-doc
In-Reply-To: <503916c8-da3b-42dd-812e-356f519be47f@infradead.org>
[-- Attachment #1: Type: text/plain, Size: 504 bytes --]
Hi Randy,
Am Freitag, 22. Mai 2026, 20:44:24 Ostafrikanische Zeit schrieben Sie:
> Does this mean that you will be merging this patch since you merged the
> original patch?
I am new to the kernel development process, so I don't know what's the
preferred way. I guess for me it is easier if your patch gets merged as-is.
I can certainly submit a pull request myself though since I made myself the
maintainer for this thing. Does that go to linux-doc@vger.kernel.org or the
soc list?
Cheers,
Stefan
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 870 bytes --]
^ permalink raw reply
* Re: [PATCH v15 12/28] drm/i915/dp: Add YCBCR444 handling for sink formats
From: Ville Syrjälä @ 2026-05-22 19:19 UTC (permalink / raw)
To: Nicolas Frattaroli
Cc: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
Jonathan Corbet, Shuah Khan, Daniel Stone, kernel, amd-gfx,
dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip,
intel-gfx, intel-xe, linux-doc, wayland-devel
In-Reply-To: <20260522-color-format-v15-12-21fb136c9df2@collabora.com>
On Fri, May 22, 2026 at 02:32:03PM +0200, Nicolas Frattaroli wrote:
> In anticipation of userspace being able to explicitly select supported
> sink formats, add handling of the YCBCR444 sink format. The AUTO path
> does not choose this format, but with explicit format selection added to
> the driver, it becomes a possibility.
>
> Check for both source and sink support of YCBCR444 in
> intel_dp_sink_format_valid.
>
> Acked-by: Daniel Stone <daniel@fooishbar.org>
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> ---
> drivers/gpu/drm/i915/display/intel_dp.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 1920d2f02666..143ed85224be 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1344,6 +1344,20 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector,
> 8, sink_format, true);
> }
>
> +static bool
> +intel_dp_can_ycbcr444(struct intel_dp *intel_dp)
> +{
> + if (source_can_output(intel_dp, INTEL_OUTPUT_FORMAT_YCBCR444) &&
> + !drm_dp_is_branch(intel_dp->dpcd))
> + return true;
> +
> + if (source_can_output(intel_dp, INTEL_OUTPUT_FORMAT_RGB) &&
> + dfp_can_convert_from_rgb(intel_dp, INTEL_OUTPUT_FORMAT_YCBCR444))
IIRC my previous conclusion was that we don't want the dfp convert
stuff here, at least initially. So this should just are about
source_can_output().
> + return true;
> +
> + return false;
> +}
> +
> static enum drm_mode_status
> intel_dp_sink_format_valid(struct intel_connector *connector,
> const struct drm_display_mode *mode,
> @@ -1364,6 +1378,13 @@ intel_dp_sink_format_valid(struct intel_connector *connector,
>
> return MODE_OK;
Again, would prefer a cleanr 420->444->rgb order.
> case INTEL_OUTPUT_FORMAT_RGB:
> + return MODE_OK;
> + case INTEL_OUTPUT_FORMAT_YCBCR444:
> + if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)))
> + return MODE_BAD;
> + if (!intel_dp_can_ycbcr444(intel_dp))
> + return MODE_BAD;
These two ifs are swapped when compared to the HDMI version for no
good reason that I can see.
And missing the has_hdmi_sink check here as well.
> +
> return MODE_OK;
> default:
> MISSING_CASE(sink_format);
>
> --
> 2.54.0
--
Ville Syrjälä
Intel
^ permalink raw reply
* Re: [PATCH v15 11/28] drm/i915/hdmi: Add YCBCR444 handling for sink formats
From: Ville Syrjälä @ 2026-05-22 19:12 UTC (permalink / raw)
To: Nicolas Frattaroli
Cc: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
Jonathan Corbet, Shuah Khan, Daniel Stone, kernel, amd-gfx,
dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip,
intel-gfx, intel-xe, linux-doc, wayland-devel
In-Reply-To: <20260522-color-format-v15-11-21fb136c9df2@collabora.com>
On Fri, May 22, 2026 at 02:32:02PM +0200, Nicolas Frattaroli wrote:
> In anticipation of userspace being able to explicitly select supported
> sink formats, add handling of the YCBCR444 sink format. The AUTO path
> does not choose this format, but with explicit format selection added to
> the driver, it becomes a possibility.
>
> Check for YCBCR444 support on the sink in sink_bpc_possible, and on the
> source and sink in sink_format_valid.
>
> Acked-by: Daniel Stone <daniel@fooishbar.org>
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> ---
> drivers/gpu/drm/i915/display/intel_hdmi.c | 32 +++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> index 9076c2b176ec..97cb321e6568 100644
> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> @@ -1966,6 +1966,8 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *_connector,
>
> if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
> return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36;
> + else if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR444)
> + return info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36;
> else
> return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36;
> case 10:
> @@ -1974,6 +1976,8 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *_connector,
>
> if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420)
> return hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_30;
> + else if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR444)
> + return info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30;
> else
> return info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30;
> case 8:
> @@ -2021,6 +2025,27 @@ intel_hdmi_mode_clock_valid(struct drm_connector *_connector, int clock,
> return status;
> }
>
> +/**
> + * intel_hdmi_can_ycbcr444 - Check whether connector can output YCbCr444
> + * @connector: pointer to &struct intel_connector to check
> + *
> + * Checks whether the hardware that backs @connector is capable of outputting
> + * YCbCr444 video over HDMI. Does not check whether currently connected sink is
> + * capable of receiving it.
> + *
> + * Returns: %true if source supports outputting YCbCr444, %false otherwise.
> + */
We don't need kernel docs for internal stuff.
> +static bool
> +intel_hdmi_can_ycbcr444(struct intel_connector *connector)
> +{
> + const struct intel_display *display = to_intel_display(connector);
> +
> + if (HAS_GMCH(display))
> + return true;
Exactly the wrong way around.
> +
> + return false;
> +}
> +
> static enum drm_mode_status
> intel_hdmi_sink_format_valid(struct intel_connector *connector,
> const struct drm_display_mode *mode,
> @@ -2038,6 +2063,13 @@ intel_hdmi_sink_format_valid(struct intel_connector *connector,
>
> return MODE_OK;
I would put the 444 stuff here between 420 and RGB. Then we logically go
from YCbCr420 -> YCbCr444 -> RGB when reading the code.
> case INTEL_OUTPUT_FORMAT_RGB:
> + return MODE_OK;
> + case INTEL_OUTPUT_FORMAT_YCBCR444:
> + if (!intel_hdmi_can_ycbcr444(connector))
> + return MODE_BAD;
We're missing the has_hdmi_sink check as well.
> + if (!(info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)))
> + return MODE_BAD;
> +
> return MODE_OK;
> default:
> MISSING_CASE(sink_format);
>
> --
> 2.54.0
--
Ville Syrjälä
Intel
^ permalink raw reply
* Re: [PATCH v5 12/13] Documentation: ABI: testing: add docs for ad9910 sysfs entries
From: Jonathan Cameron @ 2026-05-22 18:20 UTC (permalink / raw)
To: Rodrigo Alencar
Cc: rodrigo.alencar, linux-iio, devicetree, linux-kernel, linux-doc,
linux-hardening, Lars-Peter Clausen, Michael Hennerich,
David Lechner, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Jonathan Corbet, Shuah Khan,
Kees Cook, Gustavo A. R. Silva
In-Reply-To: <vqqvn2cgs3fbp5mq6xfac7iyosaqfrvgngqur4x355a3at7slo@ylrtd6fhi33a>
On Wed, 20 May 2026 19:47:25 +0100
Rodrigo Alencar <455.rodrigo.alencar@gmail.com> wrote:
> On 26/05/17 07:37PM, Rodrigo Alencar via B4 Relay wrote:
> > From: Rodrigo Alencar <rodrigo.alencar@analog.com>
> >
> > Add custom ABI documentation file for the DDS AD9910 with sysfs entries to
> > control Parallel Port, Digital Ramp Generator and OSK parameters.
>
> ...
>
> > +What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency_offset
> > +KernelVersion:
> > +Contact: linux-iio@vger.kernel.org
> > +Description:
> > + For a channel that allows frequency control through buffers, this
> > + represents the base frequency value in Hz. The actual output frequency
> > + is derived from this offset combined with the processed buffer sample
> > + value.
> > +
> > +What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_frequency_scale
> > +KernelVersion:
> > +Contact: linux-iio@vger.kernel.org
> > +Description:
> > + For a channel that allows frequency control through buffers, this
> > + represents the frequency modulation gain. This value multiplies the
> > + buffer input sample value before it is added to a frequency offset.
> > +
> > +What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_phase_offset
> > +KernelVersion:
> > +Contact: linux-iio@vger.kernel.org
> > +Description:
> > + For a channel that allows phase control through buffers, this
> > + represents the base phase value in radians. The actual output phase is
> > + derived from this offset combined with the processed buffer sample
> > + value.
> > +
> > +What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale_offset
> > +KernelVersion:
> > +Contact: linux-iio@vger.kernel.org
> > +Description:
> > + For a channel that allows amplitude control through buffers, this
> > + represents the value for a base amplitude scale. The actual output
> > + amplitude scale is derived from this offset combined with the processed
> > + buffer sample value.
> > +
>
> This will become just offset with altcurrent channels. I noticed we have a IIO_PHASE
> iio_chan_type, could we have a IIO_FREQUENCY too? Parallel port needs actual raw
> frequency values in that case to be written to the dma buffer.
>
Sure to IIO_FREQUENCY. I thought we already did but seems not!
The Phase one is a bit special given it's use in resolvers and distance sensors
but perhaps it is the right solution here.
> Then we may have buffer capable channels for the parallel port:
>
> out_altcurrent120
> offset
So that's the amplitude envelope control.
> out_phase120
> offset
So this is the phase adjustment being controlled.
> out_frequency120
And this is the frequency being controlled.
> scale
> offset
>
> Problem is that the math for the actual frequency output is:
>
> f_OUT = f_FTW + (f_RAW * FM)
>
> where f_FTW is a base frequency (already scaled), FM is a
> modulation gain and f_RAW is the contribution from the parallel
> port, which is the already scaled:
>
> f_RAW = RAW * f_SYSCLK / 2^32
> f_FTW = FTW * f_SYSCLK / 2^32
>
> so the above becomes:
>
> f_OUT = (FTW * f_SYSCLK / 2^32) + (RAW * f_SYSCLK / 2^32) * FM
> f_OUT = (FTW/FM + RAW) * f_SYSCLK * FM / 2^32
>
> if I make:
>
> SCALE = f_SYSCLK * FM / 2^32
> OFFSET = FTW/FM
> f_OUT = (OFFSET + RAW) * SCALE
>
> That would work for a IIO_FREQUENCY channel type, problem is that both
> scale and offset would depend on the modulation gain (FM)... I suppose
> scale should be setting that and offset assumes it is constant to act
> only on FTW.
I'm not that concerned about the coupling - it's a bit of a useability
issue I guess as not obvious which should be the fixed one. Can we do
cache written values and try and compensate to get a pair that is nearest
to whatever we try to drive (in either order of setting them?)
>
> I suppose we can keep altcurrent for other modes as phase and frequency
> can be attributes (knobs) for them. However, in parallel mode we are effectively
> pushing frequency, phase or amplitude values into the buffer.
Given that's the thing we are controlling. My Friday evening tired brain agrees
that it makes sense to use channel types rather than adjustments on something else.
I'll think some more on this. We've never had continuous (well digital
so near continous) control of either phase or frequency before - it's just
be symbol stuff with a couple of points to set.
>
> The polar destination is a corner case, but can be solved when both
> phase and altcurrent channels are enabled. When that happens we can
> change the scan_type with has_ext_scan_type = 1, so the 16-bit data
> bus is split between the two.
>
For now I'll just nod at that!
> With the above, all of those *_offset and *_scale custom ABI can be dropped.
That is definitely attractive :)
Jonathan
>
^ permalink raw reply
* Re: [PATCH net-next V2 2/2] net/mlx5: implement max_sfs parameter
From: Jakub Kicinski @ 2026-05-22 18:19 UTC (permalink / raw)
To: tariqt
Cc: Jakub Kicinski, edumazet, pabeni, andrew+netdev, davem, jiri,
horms, corbet, skhan, saeedm, leon, mbloch, vdumitrescu,
aleksandr.loktionov, daniel.zahka, dsahern, razor, netdev,
linux-doc, linux-kernel, linux-rdma, gal, dtatulea, jiri, nikolay
In-Reply-To: <20260519200436.353249-3-tariqt@nvidia.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net/mlx5: implement max_sfs parameter
This patch adds a generic devlink permanent parameter named max_sfs to
the mlx5 driver so users can cap the number of light-weight NIC
subfunctions via devlink instead of vendor tooling. The setter rewrites
non-volatile firmware fields in nv_global_pci_conf and nv_pf_pci_conf,
and a reboot is required for the change to take effect.
A few questions on the implementation below.
> diff --git a/Documentation/networking/devlink/mlx5.rst b/Documentation/networking/devlink/mlx5.rst
> index 4bba4d780a4a..f5e2dccafa5a 100644
> --- a/Documentation/networking/devlink/mlx5.rst
> +++ b/Documentation/networking/devlink/mlx5.rst
> @@ -45,8 +45,13 @@ Parameters
> - The range is between 1 and a device-specific max.
> - Applies to each physical function (PF) independently, if the device
> supports it. Otherwise, it applies symmetrically to all PFs.
> + * - ``max_sfs``
> + - permanent
> + - The range is between 0 and a device-specific max.
> + - Applies to each physical function (PF) independently.
[Medium, Medium]
The documentation states the range is "between 0 and a device-specific
max", and the entry says max_sfs "Applies to each physical function (PF)
independently" with no "if the device supports it" qualifier like
total_vfs has.
Looking at the implementation in mlx5_devlink_max_sfs_set(), there is no
read of any nv_global_pci_cap field to obtain a device-reported maximum,
and the registration uses NULL for the validate callback:
DEVLINK_PARAM_GENERIC(MAX_SFS, BIT(DEVLINK_PARAM_CMODE_PERMANENT),
mlx5_devlink_max_sfs_get,
mlx5_devlink_max_sfs_set, NULL),
Should there be a validate callback analogous to
mlx5_devlink_total_vfs_validate() that reads the cap and rejects values
above the device-reported maximum, so the documented "device-specific
max" is actually enforced?
Should the doc also include the "if the device supports it" qualifier
to match how the setter behaves on devices without the relevant
capability?
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c
> index 19bb620b7436..eff3a67e4ca0 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c
> @@ -68,7 +68,9 @@ struct mlx5_ifc_mnvda_reg_bits {
>
> struct mlx5_ifc_nv_global_pci_conf_bits {
> u8 sriov_valid[0x1];
> - u8 reserved_at_1[0x10];
> + u8 reserved_at_1[0xa];
> + u8 per_pf_num_sf[0x1];
> + u8 reserved_at_c[0x5];
> u8 per_pf_total_vf[0x1];
> u8 reserved_at_12[0xe];
[ ... ]
> @@ -93,9 +95,11 @@ struct mlx5_ifc_nv_global_pci_cap_bits {
> };
>
> struct mlx5_ifc_nv_pf_pci_conf_bits {
> - u8 reserved_at_0[0x9];
> + u8 log_sf_bar_size[0x8];
> + u8 pf_total_sf_en[0x1];
> u8 pf_total_vf_en[0x1];
> - u8 reserved_at_a[0x16];
> + u8 reserved_at_a[0x6];
> + u8 total_sf[0x10];
>
> u8 reserved_at_20[0x20];
[Medium]
The on-wire field total_sf is 16 bits wide, but the devlink parameter
is registered as DEVLINK_PARAM_TYPE_U32 (max_sfs uses
DEVLINK_PARAM_GENERIC_MAX_SFS_TYPE, which is u32) and the setter writes
ctx->val.vu32 directly via MLX5_SET(nv_pf_pci_conf, data, total_sf,
ctx->val.vu32).
MLX5_SET masks the value with __mlx5_mask(typ, fld) before storing, so
any user-supplied value above 0xffff is silently truncated. For
example, "devlink dev param set ... name max_sfs value 70000" would
persistently store 4464.
Without a validate callback, is there anything that prevents this
silent truncation, and should the setter or a validate hook reject
values that do not fit in 16 bits?
> @@ -755,6 +759,76 @@ static int mlx5_devlink_total_vfs_validate(struct devlink *devlink, u32 id,
> return 0;
> }
>
> +static int mlx5_devlink_max_sfs_get(struct devlink *devlink, u32 id,
> + struct devlink_param_gset_ctx *ctx,
> + struct netlink_ext_ack *extack)
> +{
> + struct mlx5_core_dev *dev = devlink_priv(devlink);
> + u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
> + void *data;
> + int err;
> +
> + err = mlx5_nv_param_read_per_host_pf_conf(dev, mnvda, sizeof(mnvda));
> + if (err) {
> + NL_SET_ERR_MSG_MOD(extack, "Failed to read PF configuration");
> + return err;
> + }
> +
> + data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
> + ctx->val.vu32 = MLX5_GET(nv_pf_pci_conf, data, total_sf);
> +
> + return 0;
> +}
[Medium]
Should max_sfs_get() mirror mlx5_devlink_total_vfs_get() and consult
nv_global_pci_conf.per_pf_num_sf before reporting nv_pf_pci_conf.total_sf?
The setter explicitly conditions the meaning of per-PF total_sf on
per_pf_num_sf:
MLX5_SET(nv_global_pci_conf, data, per_pf_num_sf, !!ctx->val.vu32);
...
MLX5_SET(nv_pf_pci_conf, data, total_sf, ctx->val.vu32);
But the getter reads total_sf unconditionally, so on a device whose
firmware was previously configured by another tool with per_pf_num_sf=0
and a stale per-host total_sf, "devlink dev param show" would return a
non-zero value that does not represent the active SF policy. Is that
intentional?
> +static int mlx5_devlink_max_sfs_set(struct devlink *devlink, u32 id,
> + struct devlink_param_gset_ctx *ctx,
> + struct netlink_ext_ack *extack)
> +{
> + struct mlx5_core_dev *dev = devlink_priv(devlink);
> + u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
> + void *data;
> + int err;
> +
> + err = mlx5_nv_param_read_global_pci_conf(dev, mnvda, sizeof(mnvda));
> + if (err) {
> + NL_SET_ERR_MSG_MOD(extack,
> + "Failed to read global PCI configuration");
> + return err;
> + }
> +
> + data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
> + MLX5_SET(nv_global_pci_conf, data, per_pf_num_sf, !!ctx->val.vu32);
> +
> + err = mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
> + if (err) {
> + NL_SET_ERR_MSG_MOD(extack,
> + "Failed to change per_pf_num_sf global PCI configuration");
> + return err;
> + }
[Medium]
Should this path first read nv_global_pci_cap and reject the operation
when the device does not advertise SF NV configuration, the way
mlx5_devlink_total_vfs_set() does for SR-IOV?
mlx5_devlink_total_vfs_set() rejects with -EOPNOTSUPP and an extack
"SRIOV is not per PF on this device" when sriov_support or
per_pf_total_vf_supported is clear, but no equivalent
per_pf_num_sf_supported (or any SF-related) capability bit is added to
nv_global_pci_cap_bits or queried here. On hardware that lacks the
feature, the user only sees the generic firmware error "Failed to
change ... global PCI configuration".
[Medium]
At this point, a successful write of per_pf_num_sf has already been
committed to non-volatile firmware storage. If the subsequent
mlx5_nv_param_read_per_host_pf_conf() or the second mlx5_nv_param_write()
fails (for example, transient firmware/PCIe issue), is there a path that
rolls back per_pf_num_sf?
Because these are permanent parameters that "require a reboot to take
effect", a half-applied state (e.g., per_pf_num_sf=1 but
pf_total_sf_en=0/total_sf=0) appears to persist across reboots until
the user issues another successful set.
> +
> + memset(mnvda, 0, sizeof(mnvda));
> + err = mlx5_nv_param_read_per_host_pf_conf(dev, mnvda, sizeof(mnvda));
> + if (err) {
> + NL_SET_ERR_MSG_MOD(extack, "Failed to read PF configuration");
> + return err;
> + }
> +
> + data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
> + MLX5_SET(nv_pf_pci_conf, data, log_sf_bar_size, ctx->val.vu32 ? 12 : 0);
[Low]
What is the meaning of the literal 12 here, and why is it correct on
all supported devices?
Elsewhere in the driver, the SF BAR length is computed from a
hardware-reported capability rather than a fixed value:
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c:
sf_bar_length = 1 << (MLX5_CAP_GEN(dev, log_min_sf_size) + 12);
Should log_sf_bar_size be derived from MLX5_CAP_GEN(dev,
log_min_sf_size) (or another cap) rather than hardcoded?
The commit message says max_sfs is to "control the total light-weight
NIC subfunctions"; the BAR-size side-effect is not mentioned, and any
previously configured log_sf_bar_size is overwritten on every
max_sfs set. Should that behavior be documented or split out from the
count knob?
> + MLX5_SET(nv_pf_pci_conf, data, pf_total_sf_en, !!ctx->val.vu32);
> + MLX5_SET(nv_pf_pci_conf, data, total_sf, ctx->val.vu32);
> +
> + err = mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
> + if (err) {
> + NL_SET_ERR_MSG_MOD(extack,
> + "Failed to change PF PCI configuration");
> + return err;
> + }
> + NL_SET_ERR_MSG(extack, "Modifying max_sfs requires a reboot");
> +
> + return 0;
> +}
--
pw-bot: cr
^ permalink raw reply
* Re: [PATCH v5 11/13] iio: frequency: ad9910: show channel priority in debugfs
From: Jonathan Cameron @ 2026-05-22 18:07 UTC (permalink / raw)
To: Rodrigo Alencar via B4 Relay
Cc: rodrigo.alencar, linux-iio, devicetree, linux-kernel, linux-doc,
linux-hardening, Lars-Peter Clausen, Michael Hennerich,
David Lechner, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Jonathan Corbet, Shuah Khan,
Kees Cook, Gustavo A. R. Silva
In-Reply-To: <20260517-ad9910-iio-driver-v5-11-31599c88314a@analog.com>
On Sun, 17 May 2026 19:37:55 +0100
Rodrigo Alencar via B4 Relay <devnull+rodrigo.alencar.analog.com@kernel.org> wrote:
> From: Rodrigo Alencar <rodrigo.alencar@analog.com>
>
> Expose frequency_source, phase_source and amplitude_source attributes in
> debugfs. Those indicate from which channel the specific DDS parameter is
> being sourced by returning its label. The implementation follows the
> priority table found in the datasheet.
>
Examples here would be good.
I guess maybe this suffers the same label problem as the parent stuff.
Same solution?
> Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
^ permalink raw reply
* Re: [PATCH v5 06/13] iio: frequency: ad9910: initial driver implementation
From: Jonathan Cameron @ 2026-05-22 18:03 UTC (permalink / raw)
To: Rodrigo Alencar via B4 Relay
Cc: rodrigo.alencar, linux-iio, devicetree, linux-kernel, linux-doc,
linux-hardening, Lars-Peter Clausen, Michael Hennerich,
David Lechner, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Jonathan Corbet, Shuah Khan,
Kees Cook, Gustavo A. R. Silva
In-Reply-To: <20260517-ad9910-iio-driver-v5-6-31599c88314a@analog.com>
On Sun, 17 May 2026 19:37:50 +0100
Rodrigo Alencar via B4 Relay <devnull+rodrigo.alencar.analog.com@kernel.org> wrote:
> From: Rodrigo Alencar <rodrigo.alencar@analog.com>
>
> Add the core AD9910 DDS driver infrastructure with single tone mode
> support. This includes SPI register access, profile management via GPIO
> pins, PLL/DAC configuration from firmware properties, and single tone
> frequency/phase/amplitude control through IIO attributes.
>
> Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
Hi Rodrigo
A couple of potential nice to haves.
Jonathan
> +
> +static int ad9910_parse_fw(struct ad9910_state *st)
> +{
> + static const char * const refclk_out_drv0[] = {
> + "disabled", "low", "medium", "high",
> + };
> + struct device *dev = &st->spi->dev;
> + u32 tmp[2];
> + int ret;
> +
> + st->data.pll_enabled = device_property_read_bool(dev, "adi,pll-enable");
> + if (st->data.pll_enabled) {
> + tmp[0] = AD9910_ICP_MIN_uA;
> + device_property_read_u32(dev, "adi,charge-pump-current-microamp", &tmp[0]);
Might be a good idea to move to the pattern that seems to be becoming
the preferred way to do this and do
if (device_property_present()) {
ret = device_property_read_u32()...
...
} else {
...
}
That is slightly nicer ad picks up malformed DT. I know I was the advocate for
the set a default and don't check ret but I'm learning!
> + if (tmp[0] < AD9910_ICP_MIN_uA || tmp[0] > AD9910_ICP_MAX_uA)
> + return dev_err_probe(dev, -ERANGE,
> + "invalid charge pump current %u\n", tmp[0]);
> + st->data.pll_charge_pump_current = tmp[0];
> +
> + ret = device_property_match_property_string(dev,
> + "adi,refclk-out-drive-strength",
> + refclk_out_drv0,
> + ARRAY_SIZE(refclk_out_drv0));
> + if (ret < 0)
Similarly good to know if failure to match actually means wasn't there or not.
> + st->data.refclk_out_drv = AD9910_REFCLK_OUT_DRV_DISABLED;
> + else
> + st->data.refclk_out_drv = ret;
> + }
> +
> + tmp[1] = AD9910_DAC_IOUT_DEFAULT_uA;
And similar again.
> + device_property_read_u32_array(dev, "output-range-microamp", tmp,
> + ARRAY_SIZE(tmp));
> + if (tmp[1] < AD9910_DAC_IOUT_MIN_uA || tmp[1] > AD9910_DAC_IOUT_MAX_uA)
> + return dev_err_probe(dev, -ERANGE,
> + "Invalid DAC output current %u uA\n", tmp[1]);
> + st->data.dac_output_current = tmp[1];
> +
> + return 0;
> +}
> +static const struct spi_device_id ad9910_id[] = {
> + { "ad9910" },
Request to simplify what Uwe is busy doing (assuming he'll get to spi
at somepoint). Please use a named initializer like we always do for
of_device_id.
> + { }
> +};
> +MODULE_DEVICE_TABLE(spi, ad9910_id);
^ permalink raw reply
* Re: [PATCH v5 10/11] PCI: liveupdate: Do not disable bus mastering on preserved devices during kexec
From: Bjorn Helgaas @ 2026-05-22 18:01 UTC (permalink / raw)
To: David Matlack
Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
Adithya Jayachandran, Alexander Graf, Alex Williamson,
Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
Pranjal Shrivastava, Pratyush Yadav, Saeed Mahameed,
Samiullah Khawaja, Shuah Khan, Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <20260512184846.119396-11-dmatlack@google.com>
On Tue, May 12, 2026 at 06:48:45PM +0000, David Matlack wrote:
> Do not disable bus mastering on outgoing preserved devices during
> pci_device_shutdown() for kexec.
>
> Preserved devices must be allowed to perform memory transactions during
> a Live Update to minimize downtime and ensure continuous operation.
> Clearing the bus mastering bit would prevent these devices from issuing
> any memory requests while the new kernel boots.
s/minimize downtime and//
Ensuring continuous operation is the critical piece here. Minimizing
downtime is always good but IMO it's not actually a reason for this
change.
I guess what this is probably saying is that the continuous operation
and Live Update are what minimizes downtime, and preserving bus
mastering is a piece of that.
> Because bridges upstream of preserved endpoint devices are also
> automatically preserved, this change also avoids clearing bus mastering
> on them. This is critical because clearing bus mastering on an upstream
> bridge prevents the bridge from forwarding memory requests upstream (i.e.
> it would prevent the endpoint device from accessing system RAM and doing
> peer-to-peer transactions with devices not downstream of the bridge).
^ permalink raw reply
* [PATCH 3/3] arm64: Sort registers in cpu-feature-registers.rst
From: Mark Brown @ 2026-05-22 17:58 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Jonathan Corbet, Shuah Khan
Cc: Peter Maydell, Joey Gouly, linux-arm-kernel, linux-doc,
linux-kernel, Mark Brown
In-Reply-To: <20260522-arm64-cpu-ftr-regs-v1-0-19775b40faf0@kernel.org>
In order to make it a bit easier to work with sort the list of registers in
cpu-feature-registers.rst lexically. There should be no content changes
resulting from this patch.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Documentation/arch/arm64/cpu-feature-registers.rst | 223 +++++++++++----------
1 file changed, 112 insertions(+), 111 deletions(-)
diff --git a/Documentation/arch/arm64/cpu-feature-registers.rst b/Documentation/arch/arm64/cpu-feature-registers.rst
index 02815db0c780..0ea294c56984 100644
--- a/Documentation/arch/arm64/cpu-feature-registers.rst
+++ b/Documentation/arch/arm64/cpu-feature-registers.rst
@@ -170,137 +170,161 @@ infrastructure:
+------------------------------+---------+---------+
- ID_AA64PFR0_EL1 - Processor Feature Register 0
+ ID_AA64ISAR1_EL1 - Instruction set attribute register 1
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | DIT | [51-48] | y |
+ | LS64 | [63-60] | y |
+------------------------------+---------+---------+
- | MPAM | [43-40] | n |
+ | I8MM | [55-52] | y |
+------------------------------+---------+---------+
- | SVE | [35-32] | y |
+ | DGH | [51-48] | y |
+------------------------------+---------+---------+
- | GIC | [27-24] | n |
+ | BF16 | [47-44] | y |
+------------------------------+---------+---------+
- | AdvSIMD | [23-20] | y |
+ | SB | [39-36] | y |
+------------------------------+---------+---------+
- | FP | [19-16] | y |
+ | FRINTTS | [35-32] | y |
+------------------------------+---------+---------+
- | EL3 | [15-12] | n |
+ | GPI | [31-28] | y |
+------------------------------+---------+---------+
- | EL2 | [11-8] | n |
+ | GPA | [27-24] | y |
+------------------------------+---------+---------+
- | EL1 | [7-4] | n |
+ | LRCPC | [23-20] | y |
+------------------------------+---------+---------+
- | EL0 | [3-0] | n |
+ | FCMA | [19-16] | y |
+ +------------------------------+---------+---------+
+ | JSCVT | [15-12] | y |
+ +------------------------------+---------+---------+
+ | API | [11-8] | y |
+ +------------------------------+---------+---------+
+ | APA | [7-4] | y |
+ +------------------------------+---------+---------+
+ | DPB | [3-0] | y |
+------------------------------+---------+---------+
-
- ID_AA64PFR1_EL1 - Processor Feature Register 1
+ ID_AA64ISAR2_EL1 - Instruction set attribute register 2
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | GCS | [47-44] | y |
+ | LUT | [59-56] | y |
+------------------------------+---------+---------+
- | SME | [27-24] | y |
+ | CSSC | [55-52] | y |
+------------------------------+---------+---------+
- | MTE | [11-8] | y |
+ | RPRFM | [51-48] | y |
+------------------------------+---------+---------+
- | SSBS | [7-4] | y |
+ | BC | [23-20] | y |
+------------------------------+---------+---------+
- | BT | [3-0] | y |
+ | MOPS | [19-16] | y |
+ +------------------------------+---------+---------+
+ | APA3 | [15-12] | y |
+ +------------------------------+---------+---------+
+ | GPA3 | [11-8] | y |
+ +------------------------------+---------+---------+
+ | RPRES | [7-4] | y |
+ +------------------------------+---------+---------+
+ | WFXT | [3-0] | y |
+------------------------------+---------+---------+
- ID_AA64PFR2_EL1 - Processor Feature Register 2
+ ID_AA64ISAR3_EL1 - Instruction set attribute register 3
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | FPMR | [35-32] | y |
+ | FPRCVT | [31-28] | y |
+------------------------------+---------+---------+
- | MTEFAR | [11-8] | y |
+ | LSFE | [19-16] | y |
+------------------------------+---------+---------+
- | MTESTOREONLY | [7-4] | y |
+ | FAMINMAX | [7-4] | y |
+------------------------------+---------+---------+
- MIDR_EL1 - Main ID Register
+ ID_AA64MMFR0_EL1 - Memory model feature register 0
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | Implementer | [31-24] | y |
- +------------------------------+---------+---------+
- | Variant | [23-20] | y |
+ | ECV | [63-60] | y |
+------------------------------+---------+---------+
- | Architecture | [19-16] | y |
+
+ ID_AA64MMFR1_EL1 - Memory model feature register 1
+
+------------------------------+---------+---------+
- | PartNum | [15-4] | y |
+ | Name | bits | visible |
+------------------------------+---------+---------+
- | Revision | [3-0] | y |
+ | AFP | [47-44] | y |
+------------------------------+---------+---------+
- NOTE: The 'visible' fields of MIDR_EL1 will contain the value
- as available on the CPU where it is fetched and is not a system
- wide safe value.
-
- ID_AA64ISAR1_EL1 - Instruction set attribute register 1
+ ID_AA64MMFR2_EL1 - Memory model feature register 2
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | LS64 | [63-60] | y |
+ | AT | [35-32] | y |
+------------------------------+---------+---------+
- | I8MM | [55-52] | y |
+
+ ID_AA64MMFR3_EL1 - Memory model feature register 3
+
+------------------------------+---------+---------+
- | DGH | [51-48] | y |
+ | Name | bits | visible |
+------------------------------+---------+---------+
- | BF16 | [47-44] | y |
+ | S1POE | [19-16] | y |
+------------------------------+---------+---------+
- | SB | [39-36] | y |
+
+ ID_AA64PFR0_EL1 - Processor Feature Register 0
+
+------------------------------+---------+---------+
- | FRINTTS | [35-32] | y |
+ | Name | bits | visible |
+------------------------------+---------+---------+
- | GPI | [31-28] | y |
+ | DIT | [51-48] | y |
+------------------------------+---------+---------+
- | GPA | [27-24] | y |
+ | MPAM | [43-40] | n |
+------------------------------+---------+---------+
- | LRCPC | [23-20] | y |
+ | SVE | [35-32] | y |
+------------------------------+---------+---------+
- | FCMA | [19-16] | y |
+ | GIC | [27-24] | n |
+------------------------------+---------+---------+
- | JSCVT | [15-12] | y |
+ | AdvSIMD | [23-20] | y |
+------------------------------+---------+---------+
- | API | [11-8] | y |
+ | FP | [19-16] | y |
+------------------------------+---------+---------+
- | APA | [7-4] | y |
+ | EL3 | [15-12] | n |
+------------------------------+---------+---------+
- | DPB | [3-0] | y |
+ | EL2 | [11-8] | n |
+ +------------------------------+---------+---------+
+ | EL1 | [7-4] | n |
+ +------------------------------+---------+---------+
+ | EL0 | [3-0] | n |
+------------------------------+---------+---------+
- ID_AA64MMFR0_EL1 - Memory model feature register 0
+
+ ID_AA64PFR1_EL1 - Processor Feature Register 1
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | ECV | [63-60] | y |
+ | GCS | [47-44] | y |
+------------------------------+---------+---------+
-
- ID_AA64MMFR2_EL1 - Memory model feature register 2
-
+ | SME | [27-24] | y |
+------------------------------+---------+---------+
- | Name | bits | visible |
+ | MTE | [11-8] | y |
+------------------------------+---------+---------+
- | AT | [35-32] | y |
+ | SSBS | [7-4] | y |
+ +------------------------------+---------+---------+
+ | BT | [3-0] | y |
+------------------------------+---------+---------+
- ID_AA64MMFR3_EL1 - Memory model feature register 3
+ ID_AA64PFR2_EL1 - Processor Feature Register 2
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | S1POE | [19-16] | y |
+ | FPMR | [35-32] | y |
+ +------------------------------+---------+---------+
+ | MTEFAR | [11-8] | y |
+ +------------------------------+---------+---------+
+ | MTESTOREONLY | [7-4] | y |
+------------------------------+---------+---------+
ID_AA6SMFR0_EL1 - SME feature ID register 0
@@ -387,50 +411,64 @@ infrastructure:
| SVEVer | [3-0] | y |
+------------------------------+---------+---------+
- ID_AA64MMFR1_EL1 - Memory model feature register 1
+ ID_ISAR5_EL1 - AArch32 Instruction Set Attribute Register 5
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | AFP | [47-44] | y |
+ | CRC32 | [19-16] | y |
+ +------------------------------+---------+---------+
+ | SHA2 | [15-12] | y |
+ +------------------------------+---------+---------+
+ | SHA1 | [11-8] | y |
+ +------------------------------+---------+---------+
+ | AES | [7-4] | y |
+------------------------------+---------+---------+
- ID_AA64ISAR2_EL1 - Instruction set attribute register 2
+ ID_ISAR6_EL1 - AArch32 Instruction Set Attribute Register 6
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | LUT | [59-56] | y |
- +------------------------------+---------+---------+
- | CSSC | [55-52] | y |
+ | I8MM | [27-24] | y |
+------------------------------+---------+---------+
- | RPRFM | [51-48] | y |
+ | BF16 | [23-20] | y |
+------------------------------+---------+---------+
- | BC | [23-20] | y |
+ | SB | [15-12] | y |
+------------------------------+---------+---------+
- | MOPS | [19-16] | y |
+ | FHM | [11-8] | y |
+------------------------------+---------+---------+
- | APA3 | [15-12] | y |
+ | DP | [7-4] | y |
+------------------------------+---------+---------+
- | GPA3 | [11-8] | y |
+
+ ID_PFR2_EL1 - AArch32 Processor Feature Register 2
+
+------------------------------+---------+---------+
- | RPRES | [7-4] | y |
+ | Name | bits | visible |
+------------------------------+---------+---------+
- | WFXT | [3-0] | y |
+ | SSBS | [7-4] | y |
+------------------------------+---------+---------+
- ID_AA64ISAR3_EL1 - Instruction set attribute register 3
+ MIDR_EL1 - Main ID Register
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
- | FPRCVT | [31-28] | y |
+ | Implementer | [31-24] | y |
+------------------------------+---------+---------+
- | LSFE | [19-16] | y |
+ | Variant | [23-20] | y |
+------------------------------+---------+---------+
- | FAMINMAX | [7-4] | y |
+ | Architecture | [19-16] | y |
+ +------------------------------+---------+---------+
+ | PartNum | [15-4] | y |
+ +------------------------------+---------+---------+
+ | Revision | [3-0] | y |
+------------------------------+---------+---------+
+ NOTE: The 'visible' fields of MIDR_EL1 will contain the value
+ as available on the CPU where it is fetched and is not a system
+ wide safe value.
+
MVFR0_EL1 - AArch32 Media and VFP Feature Register 0
+------------------------------+---------+---------+
@@ -457,43 +495,6 @@ infrastructure:
| SIMDLS | [11-8] | y |
+------------------------------+---------+---------+
- ID_ISAR5_EL1 - AArch32 Instruction Set Attribute Register 5
-
- +------------------------------+---------+---------+
- | Name | bits | visible |
- +------------------------------+---------+---------+
- | CRC32 | [19-16] | y |
- +------------------------------+---------+---------+
- | SHA2 | [15-12] | y |
- +------------------------------+---------+---------+
- | SHA1 | [11-8] | y |
- +------------------------------+---------+---------+
- | AES | [7-4] | y |
- +------------------------------+---------+---------+
-
- ID_ISAR6_EL1 - AArch32 Instruction Set Attribute Register 6
-
- +------------------------------+---------+---------+
- | Name | bits | visible |
- +------------------------------+---------+---------+
- | I8MM | [27-24] | y |
- +------------------------------+---------+---------+
- | BF16 | [23-20] | y |
- +------------------------------+---------+---------+
- | SB | [15-12] | y |
- +------------------------------+---------+---------+
- | FHM | [11-8] | y |
- +------------------------------+---------+---------+
- | DP | [7-4] | y |
- +------------------------------+---------+---------+
-
- ID_PFR2_EL1 - AArch32 Processor Feature Register 2
-
- +------------------------------+---------+---------+
- | Name | bits | visible |
- +------------------------------+---------+---------+
- | SSBS | [7-4] | y |
- +------------------------------+---------+---------+
Appendix I: Example
-------------------
--
2.47.3
^ permalink raw reply related
* [PATCH 2/3] arm64: Document missing bitfields in cpu-feature-registers.rst
From: Mark Brown @ 2026-05-22 17:58 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Jonathan Corbet, Shuah Khan
Cc: Peter Maydell, Joey Gouly, linux-arm-kernel, linux-doc,
linux-kernel, Mark Brown
In-Reply-To: <20260522-arm64-cpu-ftr-regs-v1-0-19775b40faf0@kernel.org>
We have been rather lax in updating the list of visible bitfields in the
ID registers in cpu-feature-registers.rst, it is currently missing several
of the registers and quite a few bitfields in existing registers. Bring it
into sync with current -next.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Documentation/arch/arm64/cpu-feature-registers.rst | 146 +++++++++++++++++++++
1 file changed, 146 insertions(+)
diff --git a/Documentation/arch/arm64/cpu-feature-registers.rst b/Documentation/arch/arm64/cpu-feature-registers.rst
index c6e5bc053c09..02815db0c780 100644
--- a/Documentation/arch/arm64/cpu-feature-registers.rst
+++ b/Documentation/arch/arm64/cpu-feature-registers.rst
@@ -113,6 +113,30 @@ infrastructure:
4. List of registers with visible features
-------------------------------------------
+ ID_AA6FPFR0_EL1 - Floating Point feature ID register 0
+
+ +------------------------------+---------+---------+
+ | Name | bits | visible |
+ +------------------------------+---------+---------+
+ | F8CVT | [31] | y |
+ +------------------------------+---------+---------+
+ | F8FMA | [30] | y |
+ +------------------------------+---------+---------+
+ | F8DP4 | [29] | y |
+ +------------------------------+---------+---------+
+ | F8DP2 | [28] | y |
+ +------------------------------+---------+---------+
+ | F8MM8 | [27] | y |
+ +------------------------------+---------+---------+
+ | F8MM4 | [26] | y |
+ +------------------------------+---------+---------+
+ | F16MM2 | [15] | y |
+ +------------------------------+---------+---------+
+ | F8E4M3 | [1] | y |
+ +------------------------------+---------+---------+
+ | F8E5M2 | [0] | y |
+ +------------------------------+---------+---------+
+
ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
+------------------------------+---------+---------+
@@ -178,6 +202,8 @@ infrastructure:
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
+ | GCS | [47-44] | y |
+ +------------------------------+---------+---------+
| SME | [27-24] | y |
+------------------------------+---------+---------+
| MTE | [11-8] | y |
@@ -187,6 +213,17 @@ infrastructure:
| BT | [3-0] | y |
+------------------------------+---------+---------+
+ ID_AA64PFR2_EL1 - Processor Feature Register 2
+
+ +------------------------------+---------+---------+
+ | Name | bits | visible |
+ +------------------------------+---------+---------+
+ | FPMR | [35-32] | y |
+ +------------------------------+---------+---------+
+ | MTEFAR | [11-8] | y |
+ +------------------------------+---------+---------+
+ | MTESTOREONLY | [7-4] | y |
+ +------------------------------+---------+---------+
MIDR_EL1 - Main ID Register
@@ -213,6 +250,8 @@ infrastructure:
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
+ | LS64 | [63-60] | y |
+ +------------------------------+---------+---------+
| I8MM | [55-52] | y |
+------------------------------+---------+---------+
| DGH | [51-48] | y |
@@ -256,6 +295,68 @@ infrastructure:
| AT | [35-32] | y |
+------------------------------+---------+---------+
+ ID_AA64MMFR3_EL1 - Memory model feature register 3
+
+ +------------------------------+---------+---------+
+ | Name | bits | visible |
+ +------------------------------+---------+---------+
+ | S1POE | [19-16] | y |
+ +------------------------------+---------+---------+
+
+ ID_AA6SMFR0_EL1 - SME feature ID register 0
+
+ +------------------------------+---------+---------+
+ | Name | bits | visible |
+ +------------------------------+---------+---------+
+ | FA64 | [63] | y |
+ +------------------------------+---------+---------+
+ | LUT6 | [61] | y |
+ +------------------------------+---------+---------+
+ | LUTv2 | [60] | y |
+ +------------------------------+---------+---------+
+ | SMEver | [59-56] | y |
+ +------------------------------+---------+---------+
+ | I16I64 | [55-52] | y |
+ +------------------------------+---------+---------+
+ | F64F64 | [48] | y |
+ +------------------------------+---------+---------+
+ | I16I32 | [47-44] | y |
+ +------------------------------+---------+---------+
+ | B16B16 | [43] | y |
+ +------------------------------+---------+---------+
+ | F16F16 | [42] | y |
+ +------------------------------+---------+---------+
+ | F8F16 | [41] | y |
+ +------------------------------+---------+---------+
+ | F8F32 | [40] | y |
+ +------------------------------+---------+---------+
+ | I8I32 | [39-36] | y |
+ +------------------------------+---------+---------+
+ | F16F32 | [35] | y |
+ +------------------------------+---------+---------+
+ | B16F32 | [34] | y |
+ +------------------------------+---------+---------+
+ | BI32I32 | [33] | y |
+ +------------------------------+---------+---------+
+ | F32F32 | [32] | y |
+ +------------------------------+---------+---------+
+ | SF8FMA | [30] | y |
+ +------------------------------+---------+---------+
+ | SF8DP4 | [29] | y |
+ +------------------------------+---------+---------+
+ | SF8DP2 | [28] | y |
+ +------------------------------+---------+---------+
+ | SBitPerm | [25] | y |
+ +------------------------------+---------+---------+
+ | AES | [24] | y |
+ +------------------------------+---------+---------+
+ | SFEXPA | [23] | y |
+ +------------------------------+---------+---------+
+ | STMOP | [16] | y |
+ +------------------------------+---------+---------+
+ | SMOP4 | [0] | y |
+ +------------------------------+---------+---------+
+
ID_AA64ZFR0_EL1 - SVE feature ID register 0
+------------------------------+---------+---------+
@@ -265,6 +366,8 @@ infrastructure:
+------------------------------+---------+---------+
| F32MM | [55-52] | y |
+------------------------------+---------+---------+
+ | F16MM | [51-48] | y |
+ +------------------------------+---------+---------+
| I8MM | [47-44] | y |
+------------------------------+---------+---------+
| SM4 | [43-40] | y |
@@ -277,6 +380,8 @@ infrastructure:
+------------------------------+---------+---------+
| BitPerm | [19-16] | y |
+------------------------------+---------+---------+
+ | EltPerm | [15-12] | y |
+ +------------------------------+---------+---------+
| AES | [7-4] | y |
+------------------------------+---------+---------+
| SVEVer | [3-0] | y |
@@ -295,6 +400,8 @@ infrastructure:
+------------------------------+---------+---------+
| Name | bits | visible |
+------------------------------+---------+---------+
+ | LUT | [59-56] | y |
+ +------------------------------+---------+---------+
| CSSC | [55-52] | y |
+------------------------------+---------+---------+
| RPRFM | [51-48] | y |
@@ -312,6 +419,18 @@ infrastructure:
| WFXT | [3-0] | y |
+------------------------------+---------+---------+
+ ID_AA64ISAR3_EL1 - Instruction set attribute register 3
+
+ +------------------------------+---------+---------+
+ | Name | bits | visible |
+ +------------------------------+---------+---------+
+ | FPRCVT | [31-28] | y |
+ +------------------------------+---------+---------+
+ | LSFE | [19-16] | y |
+ +------------------------------+---------+---------+
+ | FAMINMAX | [7-4] | y |
+ +------------------------------+---------+---------+
+
MVFR0_EL1 - AArch32 Media and VFP Feature Register 0
+------------------------------+---------+---------+
@@ -327,6 +446,10 @@ infrastructure:
+------------------------------+---------+---------+
| SIMDFMAC | [31-28] | y |
+------------------------------+---------+---------+
+ | FPHP | [27-24] | y |
+ +------------------------------+---------+---------+
+ | SIMDHP | [23-20] | y |
+ +------------------------------+---------+---------+
| SIMDSP | [19-16] | y |
+------------------------------+---------+---------+
| SIMDInt | [15-12] | y |
@@ -348,6 +471,29 @@ infrastructure:
| AES | [7-4] | y |
+------------------------------+---------+---------+
+ ID_ISAR6_EL1 - AArch32 Instruction Set Attribute Register 6
+
+ +------------------------------+---------+---------+
+ | Name | bits | visible |
+ +------------------------------+---------+---------+
+ | I8MM | [27-24] | y |
+ +------------------------------+---------+---------+
+ | BF16 | [23-20] | y |
+ +------------------------------+---------+---------+
+ | SB | [15-12] | y |
+ +------------------------------+---------+---------+
+ | FHM | [11-8] | y |
+ +------------------------------+---------+---------+
+ | DP | [7-4] | y |
+ +------------------------------+---------+---------+
+
+ ID_PFR2_EL1 - AArch32 Processor Feature Register 2
+
+ +------------------------------+---------+---------+
+ | Name | bits | visible |
+ +------------------------------+---------+---------+
+ | SSBS | [7-4] | y |
+ +------------------------------+---------+---------+
Appendix I: Example
-------------------
--
2.47.3
^ permalink raw reply related
* Re: [PATCH v5 05/11] PCI: liveupdate: Keep bus numbers constant during Live Update
From: Bjorn Helgaas @ 2026-05-22 17:59 UTC (permalink / raw)
To: David Matlack
Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
Adithya Jayachandran, Alexander Graf, Alex Williamson,
Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
Pranjal Shrivastava, Pratyush Yadav, Saeed Mahameed,
Samiullah Khawaja, Shuah Khan, Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <20260512184846.119396-6-dmatlack@google.com>
On Tue, May 12, 2026 at 06:48:40PM +0000, David Matlack wrote:
> ...
> + * The PCI core guarantees that preserved devices can be identified by the same
> + * bus, device, and function numbers for as long as they are preserved
> + * (including across kexec). To accomplish this, the PCI core always inherits
> + * the secondary and subordinate bus numbers assigned to bridges during scanning
> + * if any device is preserved. This is true even on architectures that always
> + * assign new bus numbers during scanning. The kernel assumes the previous
> + * kernel established a sane bus topology across kexec.
> + *
> + * If a misconfigured or unconfigured bridge is encountered during enumeration
> + * while there are preserved devices, itss secondary and subordinate bus numbers
> + * will be cleared and devices below it will not be enumerated.
s/itss/its/
> + * To keep things simple, inherit the secondary and subordinate bus numbers on
> + * _all_ bridges if _any_ PCI devices are preserved (i.e. even bridges without
> + * any downstream endpoints that were preserved). This avoids accidentally
> + * assigning a bridge a new window that overlaps with a preserved device that is
> + * downstream of a different bridge.
s/i.e. even/i.e. even/ (remove extra space)
^ permalink raw reply
* [PATCH 1/3] arm64: Don't number registers in cpu-feature-registers.rst
From: Mark Brown @ 2026-05-22 17:58 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Jonathan Corbet, Shuah Khan
Cc: Peter Maydell, Joey Gouly, linux-arm-kernel, linux-doc,
linux-kernel, Mark Brown
In-Reply-To: <20260522-arm64-cpu-ftr-regs-v1-0-19775b40faf0@kernel.org>
cpu-feature-regsters.rst documents the set of userspace visible ID
registers. At present the section for each register is numbered, this has
lead to the registers being documented in a haphazard order as new ones
have been added to the end of the list to avoid renumbering. Remove the
numbers so we can avoid this problem in future.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Documentation/arch/arm64/cpu-feature-registers.rst | 26 +++++++++++-----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/Documentation/arch/arm64/cpu-feature-registers.rst b/Documentation/arch/arm64/cpu-feature-registers.rst
index add66afc7b03..c6e5bc053c09 100644
--- a/Documentation/arch/arm64/cpu-feature-registers.rst
+++ b/Documentation/arch/arm64/cpu-feature-registers.rst
@@ -113,7 +113,7 @@ infrastructure:
4. List of registers with visible features
-------------------------------------------
- 1) ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
+ ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -146,7 +146,7 @@ infrastructure:
+------------------------------+---------+---------+
- 2) ID_AA64PFR0_EL1 - Processor Feature Register 0
+ ID_AA64PFR0_EL1 - Processor Feature Register 0
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -173,7 +173,7 @@ infrastructure:
+------------------------------+---------+---------+
- 3) ID_AA64PFR1_EL1 - Processor Feature Register 1
+ ID_AA64PFR1_EL1 - Processor Feature Register 1
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -188,7 +188,7 @@ infrastructure:
+------------------------------+---------+---------+
- 4) MIDR_EL1 - Main ID Register
+ MIDR_EL1 - Main ID Register
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -208,7 +208,7 @@ infrastructure:
as available on the CPU where it is fetched and is not a system
wide safe value.
- 5) ID_AA64ISAR1_EL1 - Instruction set attribute register 1
+ ID_AA64ISAR1_EL1 - Instruction set attribute register 1
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -240,7 +240,7 @@ infrastructure:
| DPB | [3-0] | y |
+------------------------------+---------+---------+
- 6) ID_AA64MMFR0_EL1 - Memory model feature register 0
+ ID_AA64MMFR0_EL1 - Memory model feature register 0
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -248,7 +248,7 @@ infrastructure:
| ECV | [63-60] | y |
+------------------------------+---------+---------+
- 7) ID_AA64MMFR2_EL1 - Memory model feature register 2
+ ID_AA64MMFR2_EL1 - Memory model feature register 2
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -256,7 +256,7 @@ infrastructure:
| AT | [35-32] | y |
+------------------------------+---------+---------+
- 8) ID_AA64ZFR0_EL1 - SVE feature ID register 0
+ ID_AA64ZFR0_EL1 - SVE feature ID register 0
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -282,7 +282,7 @@ infrastructure:
| SVEVer | [3-0] | y |
+------------------------------+---------+---------+
- 8) ID_AA64MMFR1_EL1 - Memory model feature register 1
+ ID_AA64MMFR1_EL1 - Memory model feature register 1
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -290,7 +290,7 @@ infrastructure:
| AFP | [47-44] | y |
+------------------------------+---------+---------+
- 9) ID_AA64ISAR2_EL1 - Instruction set attribute register 2
+ ID_AA64ISAR2_EL1 - Instruction set attribute register 2
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -312,7 +312,7 @@ infrastructure:
| WFXT | [3-0] | y |
+------------------------------+---------+---------+
- 10) MVFR0_EL1 - AArch32 Media and VFP Feature Register 0
+ MVFR0_EL1 - AArch32 Media and VFP Feature Register 0
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -320,7 +320,7 @@ infrastructure:
| FPDP | [11-8] | y |
+------------------------------+---------+---------+
- 11) MVFR1_EL1 - AArch32 Media and VFP Feature Register 1
+ MVFR1_EL1 - AArch32 Media and VFP Feature Register 1
+------------------------------+---------+---------+
| Name | bits | visible |
@@ -334,7 +334,7 @@ infrastructure:
| SIMDLS | [11-8] | y |
+------------------------------+---------+---------+
- 12) ID_ISAR5_EL1 - AArch32 Instruction Set Attribute Register 5
+ ID_ISAR5_EL1 - AArch32 Instruction Set Attribute Register 5
+------------------------------+---------+---------+
| Name | bits | visible |
--
2.47.3
^ permalink raw reply related
* [PATCH 0/3] arm64: Fixes and cleanups for cpu-feature-registers.rst
From: Mark Brown @ 2026-05-22 17:58 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Jonathan Corbet, Shuah Khan
Cc: Peter Maydell, Joey Gouly, linux-arm-kernel, linux-doc,
linux-kernel, Mark Brown
Peter Maydell noticed some missing updates to cpu-feature-registers.rst,
while looking at these a number of other other omissions and some
maintainability problems were observed. Several registers and many
bitfields have not been added.
Following discussion with Catalin we remove the numbering of the
registers in the first patch so that when we add the registers we can
add them in a roughly sorted order, then fix up the missing
documentation before sorting the existing entries in the file.
This whole area should have much better tooling, rather than having to
update multiple places and manually cross check several different places
including rarely used documentation we should be marking up the sysreg
descriptions and then either generating the data or validating against
manually updated copies. Manually updated copies seem like a good idea
for the ABI documentation since while it's more work that would force
review. I did start on some sketches, it seemed like it might make
sense to tackle along with using the MRS but the libraries for that
seem not to be progressing at any great rate, I'll dig the sketches out.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Mark Brown (3):
arm64: Don't number registers in cpu-feature-registers.rst
arm64: Document missing bitfields in cpu-feature-registers.rst
arm64: Sort registers in cpu-feature-registers.rst
Documentation/arch/arm64/cpu-feature-registers.rst | 281 ++++++++++++++++-----
1 file changed, 214 insertions(+), 67 deletions(-)
---
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
change-id: 20260521-arm64-cpu-ftr-regs-bceb2d34376f
Best regards,
--
Mark Brown <broonie@kernel.org>
^ permalink raw reply
* [PATCH net-next] Documentation: networking: Add a test plan for ethtool pause validation
From: Maxime Chevallier (Netdev Foundation) @ 2026-05-22 17:51 UTC (permalink / raw)
To: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Russell King, Heiner Kallweit, Jonathan Corbet,
Shuah Khan
Cc: Maxime Chevallier (Netdev Foundation), Oleksij Rempel,
Vladimir Oltean, Florian Fainelli, thomas.petazzoni, netdev,
linux-kernel, linux-doc
Flow control configuration through Ethernet Pause frames is not
straightforward to get right when implementing a MAC or a PHY driver.
This is often a feature that's poorly tested during development, and
getting it right requires correct configuration both in MAC drivers,
that implement the flow-control, and the PHY drivers, which deal with
the negotiation of the pause parameters.
As part of the Netdev Foundation effort to improve driver testing, and to ease
the development and review effort, The netdev mailing list has been surveyed
to identify the common pitfalls. This testing plan has been written to try and
catch most of the common problems.
This document is aimed as being a human readable basis we can adjust and
discuss before diving into the actual tests implementation, it may not
necessarily have to live in the kernel doc forever, especially once
tests are implemented.
Note that Oleksij Rempel made some attempts at documenting Ethernet Flow-control
before [1], this current work isn't meant to superseed it but rather
complement it with a testing protocol.
[1] : https://lore.kernel.org/netdev/20260304094811.2779953-1-o.rempel@pengutronix.de/
Signed-off-by: Maxime Chevallier (Netdev Foundation) <maxime.chevallier@bootlin.com>
---
Temptative approach to send that as part of the kdoc, this may not be
the best path, as this could simply be some email thread.
Documentation/networking/index.rst | 1 +
Documentation/networking/pause_test_plan.rst | 556 +++++++++++++++++++
2 files changed, 557 insertions(+)
create mode 100644 Documentation/networking/pause_test_plan.rst
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index 44a422ad3b05..fef54999267d 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -91,6 +91,7 @@ Contents:
openvswitch
operstates
packet_mmap
+ pause_test_plan
phonet
phy-link-topology
phy-port
diff --git a/Documentation/networking/pause_test_plan.rst b/Documentation/networking/pause_test_plan.rst
new file mode 100644
index 000000000000..5ff9860efbe5
--- /dev/null
+++ b/Documentation/networking/pause_test_plan.rst
@@ -0,0 +1,556 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Ethtool Pause testing
+=====================
+
+This document describes the test plan to be used for the ethtool selftest, aimed
+at providing a validation framework for Ethernet drivers that implement flow-control.
+
+To ease readability, the document uses the "ethtool" command to describe test cases,
+actual tests may use the netlink API directly.
+
+This document was written after surveying the common error patterns for pause-related
+patches on the netdev mailing list. The common mistakes are usually found in either
+MAC drivers that don't make use of phylink, or PHY drivers that interfere with
+pause settings.
+
+The main classes of problems are :
+
+ - MAC drivers incorrectly configuring the Pause/Asym capabilities in the attached
+ PHY device through calling phy_support_asym_pause() and phy_support_sym_pause().
+
+ These are used to allow the PHY do know what Pause settings the MAC supports, in
+ order to advertise it to the LP.
+
+ They aren't to be used to configure the Pause advertisement, and the MAC driver
+ needs to actually configure Pause on its side after negotiation finishes.
+
+ Using phylink is the easiest fix for this kind of problem.
+
+ - PHY drivers overriding the Pause/AsymPause bits in the supported/advertising
+ fields. Pause is a MAC feature, but the PHY negotiates the settings with the
+ partner. The PHY driver shouldn't have to tweak Pause settings, only advertise
+ them and report the negotiation results.
+
+ - MAC drivers confusing phydev->autoneg and pause autoneg. Pause autoneg is about
+ whether or not we want to negotiate the Pause settings with the partner, or use
+ locally enforced settings. phydev->autoneg, also referred to as link-wide autoneg
+ is about whether or not we want to negotiate anything with the link partner,
+ including speed, duplex, pause, etc. Both phydev->autoneg and pause autoneg can
+ be configured independently.
+
+ - MAC drivers mishandling the pause parameters in the ethtool get/set_pauseparam
+ callbacks, usually by ignoring the pause autoneg settings.
+
+The hardware capabilities regarding Pause support are reported through the
+linkmodes bits 'ETHTOOL_LINK_MODE_Pause' and 'ETHTOOL_LINK_MODE_Asym_Pause', the
+four different combinations are accepted and together describe the ability for
+the hardware to send TX pause frames, and process the received ones :
+
+ - **Pause** bit : the interface has the ability to Receive and process Pause frames
+ - **Asym** bit (Or AsymDir) : The TX and RX pause setting can be different.
+
+This translates to :
+
+ - **Pause** & **Asym** : We can support **ALL** combinations of rx/tx
+
+ - **Pause only** : only **rx == tx** configurations are valid
+
+ - **Asym** only : **rx** must be **off**, **tx** can be **on or off**
+
+Similarly, the link partner can advertise its capabilities through the same
+bits. These parameters are exchanged through the negotiation process, but can
+also be enforced locally by disabling **pause autoneg**, thus ignoring the
+link partner's capabilities.
+
+The local resolution of the pause configuration after receiving the link-partner
+abilities is done according to the following table, from 802.3 Annex 28B.3 :
+
++-------------+--------------+--------------------------+
+|Local device | Link partner | Pause settings resolution|
++------+------+-------+------+-----------+--------------+
+|Pause | Asym | Pause | Asym | RX | TX |
++======+======+=======+======+===========+==============+
+| 0 | 0 | Any | Any | No | No |
++------+------+-------+------+-----------+--------------+
+| 0 | 1 | 0 | Any | No | No |
++------+------+-------+------+-----------+--------------+
+| 0 | 1 | 1 | 0 | No | No |
++------+------+-------+------+-----------+--------------+
+| 0 | 1 | 1 | 1 | No | Yes |
++------+------+-------+------+-----------+--------------+
+| 1 | 0 | 0 | Any | No | No |
++------+------+-------+------+-----------+--------------+
+| 1 | Any | 1 | Any | Yes | Yes |
++------+------+-------+------+-----------+--------------+
+| 1 | 1 | 0 | 0 | No | No |
++------+------+-------+------+-----------+--------------+
+| 1 | 1 | 0 | 1 | Yes | No |
++------+------+-------+------+-----------+--------------+
+
+The currently configured and advertised settings can be queried with ::
+
+ ethtool <iface>
+
+ Settings for eth0:
+ ...
+ Supported pause frame use: Symmetric Receive-only
+ ...
+ Advertised pause frame use: Symmetric Receive-only
+ ...
+ Link partner advertised pause frame use: Symmetric Receive-only
+
+While testing can be done directly with the Netlink API, as a reminder here's
+what the ethtool output translates to :
+
++------------------------+-------+---------+
+| Ethtool output | Pause | AsymDir |
++========================+=======+=========+
+| No | 0 | 0 |
++------------------------+-------+---------+
+| Transmit-only | 0 | 1 |
++------------------------+-------+---------+
+| Symmetric | 1 | 0 |
++------------------------+-------+---------+
+| Symmetric Receive-only | 1 | 1 |
++------------------------+-------+---------+
+
+Mac drivers's current pause behaviour is reported through the
+ethtool -a/--show-pause command, e.g.::
+
+ ethtool -a <iface>
+
+ Autonegotiate: on
+ RX: off
+ TX: off
+ RX negotiated: on
+ TX negotiated: on
+
+When **pause autoneg** is on, the currently used pause parameters are the
+*negotiated* ones, that may differ from the user-specified rx and tx values.
+
+When **pause autoneg** is off, the rx and tx values are the ones used by the
+hardware.
+
+A : Standalone driver testing
+=============================
+
+Requirements : The interface under test must be connected to a link-partner whose
+interface is admin-up. We don't require the link-partner to be configured in any
+other specific manner for these tests.
+
+A.1 : Sanity Checks
+~~~~~~~~~~~~~~~~~~~
+
+Pause autoneg is set to off::
+
+ ethtool -A <iface> autoneg off
+
+The 'supported' fields retrieved using the ETHTOOL_MSG_LINKMODES_GET includes
+a "Pause" bit and an "Asym" bit.
+
+The ETHTOOL_MSG_PAUSE_GET command returns the currently configured pause modes
+in the "tx" and "rx" attributes.
+
+These parameters must validate against the following truth table :
+
+ +--------------+-----------------+
+ | linkmodes | pauseparam |
+ +-------+------+--------+--------+
+ | Pause | Asym | rx | tx |
+ +=======+======+========+========+
+ | 0 | 0 | 0 | 0 |
+ +-------+------+--------+--------+
+ | 0 | 1 | 0 | 0 or 1 |
+ +-------+------+--------+--------+
+ | 1 | 0 | rx == tx |
+ +-------+------+--------+--------+
+ | 1 | 1 | 0 or 1 | 0 or 1 |
+ +-------+------+--------+--------+
+
+Test scenario
+-------------
+
+Following the reported value from::
+
+ ethtool <iface>
+ Settings for <iface>:
+ ...
+ Supported pause frame use: <value>
+
+Iterate over all the 4 combinations of rx and tx pause parameters::
+
+ ethtool -A <iface> autoneg off rx <rx_val> tx <tx_val>
+
+The settings must be accepted or rejected, according to the above truth table.
+
+Failing this test likely means the MAC driver is incorrectly setting the PHY's
+Pause and AsymDir bits, or that the PHY driver overwrites the Pause and AsymDir
+supported bits.
+
+A.2 : Half-duplex operation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Pause settings as exposed with the ethtool API only concern full-duplex modes.
+
+Test scenario:
+--------------
+
+Set the interface under test in half-duplex mode with::
+
+ ethtool -s <iface> duplex half
+
+Expected behaviour::
+
+ - ethtool <iface>
+
+shows no Pause settings advertised.
+
+Should this test fail, it likely means that either the MAC driver incorrectly
+calls phydev_set_asym_pause(), or that the PHY driver overrides the settings.
+
+B : Combined devices testing
+============================
+
+Requirements : The interface under test must be connected to a link-partner that
+can be actively configured during the tests. It must at least support full-duplex
+modes, and optionally (but ideally) symmetric and asymmetric flow-control, as
+well as autonegotiation of the Pause parameters.
+
+B.1 : Autoneg advertising
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Goal: Validate that the *advertised* Pause and AsymDir bits match the configured
+pausemarams.
+
+The link-level autonegotiation must be enabled::
+
+ ethtool <iface> autoneg on
+
+Pause parameters are set with::
+
+ ethtool -A <iface> rx <val> tx <val> autoneg on
+
+Pause advertising is retrieved with::
+
+ ethtool <iface>
+
+Case 1
+------
+
+Pause parameters : rx **off** tx **off**
+
+Expected advertisement : **None** (Pause = 0, AsymDir = 0)
+
+Case 2
+------
+
+Pause parameters : rx **off** tx **on**
+
+Expected advertisement : **Transmit-only** (Pause = 0, AsymDir = 1)
+
+Case 3
+------
+
+Pause parameters : rx **on** tx **off**
+
+Expected advertisement : **Symmetric receive-only** (Pause = 1, Asymdir = 1)
+
+Case 4
+------
+
+Pause parameters : rx **on** tx **on**
+
+Expected advertisement : **Symmetric** (Pause = 1, Asymdir = 0)
+
+B.2 : Autoneg resolution
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Goal: Validate that the Pause and AsymDir negotiation translates to the right
+TX and RX pause parameters.
+
+The following table, from the 802.3 standard, exposes the autoneg resolution
+result for the advertised pause parameters by each link partner.
+
++-------------+--------------+--------------------------+
+|Local device | Link partner | Pause settings resolution|
++------+------+-------+------+-----------+--------------+
+|Pause | Asym | Pause | Asym | RX | TX |
++======+======+=======+======+===========+==============+
+| 0 | 0 | Any | Any | No | No |
++------+------+-------+------+-----------+--------------+
+| 0 | 1 | 0 | Any | No | No |
++------+------+-------+------+-----------+--------------+
+| 0 | 1 | 1 | 0 | No | No |
++------+------+-------+------+-----------+--------------+
+| 0 | 1 | 1 | 1 | No | Yes |
++------+------+-------+------+-----------+--------------+
+| 1 | 0 | 0 | Any | No | No |
++------+------+-------+------+-----------+--------------+
+| 1 | Any | 1 | Any | Yes | Yes |
++------+------+-------+------+-----------+--------------+
+| 1 | 1 | 0 | 0 | No | No |
++------+------+-------+------+-----------+--------------+
+| 1 | 1 | 0 | 1 | Yes | No |
++------+------+-------+------+-----------+--------------+
+
+The mapping between the configured pause parameters and advertised modes follow
+the following truth table :
+
++----+----+-------+---------+
+| tx | rx | Pause | AsymDir |
++====+====+=======+=========+
+| 0 | 0 | 0 | 0 |
++----+----+-------+---------+
+| 0 | 1 | 1 | 1 |
++----+----+-------+---------+
+| 1 | 0 | 0 | 1 |
++----+----+-------+---------+
+| 1 | 1 | 1 | 0 |
++----+----+-------+---------+
+
+We can boil that down to the following cases to test, keeping the number small
+to avoid dealing with the whole combinatory::
+
+ ethtool -A <iface> autoneg on rx <rx_param> tx <tx_param>
+
+Failing tests here would likely indicate that the MAC driver doesn't correctly
+accounts for the negotiated Pause parameters in its .adjust_link() callback. A
+MAC driver that uses phylink should pass these tests.
+
+Case 1
+------
+
+Local device : rx **off**, tx **off**
+Remote device : rx **on** tx **on**
+
+Expected result on local device after autonegotiation completes :
+ rx negotiated **off**
+ tx negotiated **off**
+
+Case 2
+------
+
+Local device : rx **off** tx **on**
+Remote device : rx **off** tx **on**
+
+Expected result on local device after autonegotiation completes :
+ rx negotiated **off**
+ tx negotiated **off**
+
+Case 3
+------
+
+Local device : rx **off** tx **on**
+Remote device : rx **on** tx **off**
+
+Expected result on local device after autonegotiation completes :
+ rx negotiated **off**
+ tx negotiated **on**
+
+Case 4
+------
+
+Local device : rx **off** tx **on**
+Remote device : rx **on** tx **on**
+
+Expected result on local device after autonegotiation completes :
+ rx negotiated **off**
+ tx negotiated **off**
+
+This case looks surprising but boils down to the fact that we advertise Asym only,
+whereas the LP is advertising Pause (and not Pause + Asym).
+
+As per 802.3 this resolves to all "Off".
+
+Case 5
+------
+
+Local device : rx **on** tx **off**
+Remote device : rx **off** tx **on**
+
+Expected result on local device after autonegotiation completes :
+ rx negotiated **on**
+ tx negotiated **off**
+
+Case 6
+------
+
+Local device : rx **on** tx **on**
+Remote device : rx **on** tx **off**
+
+Expected result on local device after autonegotiation completes :
+ rx negotiated **on**
+ tx negotiated **on**
+
+This is also not an obvious result. We advertise Pause, the Link partner advertises
+Pause + Asym, so it resolves to all "On".
+
+Case 7
+------
+
+Local device : rx **on** tx **on**
+Remote device : rx **off** tx **off**
+
+Expected result on local device after autonegotiation completes :
+ rx negotiated **off**
+ tx negotiated **off**
+
+Case 8
+------
+
+Local device : rx **on** tx **on**
+Remote device : rx **off** tx **on**
+
+Expected result on local device after autonegotiation completes :
+ rx negotiated **on**
+ tx negotiated **off**
+
+B.3 : Pause Autoneg
+~~~~~~~~~~~~~~~~~~~
+
+Goal: Validate that the Pause autonegotiation flag correctly toggles the
+advertised Pause and AsymDir link parameters.
+
+Test scenario:
+--------------
+
+ - Enable pause autoneg and at least rx or tx pause::
+
+ ethtool -A <iface> rx on tx on autoneg on
+
+ - Check the Advertised pause frame use::
+
+ ethtool <iface>
+
+ ...
+ Advertised pause frame use: Symmetric Receive-only
+
+ - Disable pause autoneg::
+
+ ethtool -A <iface> autoneg off
+
+ - Check the Advertised pause frame use, which must be 'No'::
+
+ ethtool <iface>
+
+ ...
+ Advertised pause frame use: No
+
+B.4 : Pause autoneg transition
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Goal: Validate the advertising and pause parameters upon toggling pause
+ autonegotiation. When pause autoneg is disabled, the local pause settings
+ are dictated by the user configuration, without relying on negotiated
+ parameters.
+
+This validation focuses on cases where the pause autoneg result differs from the
+user-specified rx and tx pauseparams, e.g. :
+
+Local device : rx **on** tx **off**
+Remote device : rx **on** tx **on**
+
+This will negotiate into rx and tx being **on**, contrary to the user intent.
+
+Test scenario:
+--------------
+
+ - Enable link-wide autonegotiation::
+
+ ethtool -s <iface> autoneg on
+
+ - Enable Pause autonegotiation, setting RX on and TX off::
+
+ ethtool -A <iface> rx on tx off autoneg on
+
+ - Expected result::
+
+ ethtool -a <iface>
+
+ Pause parameters for <iface>:
+ Autonegotiate: on
+ RX: on
+ TX: off
+ RX negotiated: on
+ TX negotiated: on
+
+Note that the currently applied configuration here is expressed by the "negotiated"
+parameters, so the link is currently using RX and TX Pauses.
+
+ - Disable pause autonegotiation::
+
+ ethtool -A <iface> autoneg off
+
+ - Expected result::
+
+ ethtool -a <iface>
+
+ Pause parameters for <iface>:
+ Autonegotiate: off
+ RX: on
+ TX: off
+
+Note that now, the currently applied configuration really is RX on TX off. It is
+expected that upon running the above command, the link flips down and up again
+as flow-control parameters are updated.
+
+ - Re-enable pause autonegotiation::
+
+ ethtool -A <iface> autoneg on
+
+ - Expected result::
+
+ ethtool -a <iface>
+
+ Pause parameters for <iface>:
+ Autonegotiate: on
+ RX: on
+ TX: off
+ RX negotiated: on
+ TX negotiated: on
+
+The user-defined pause parameters needs to be again converted to advertised Pause
+and Asym parameters, negotiated and the final outcome must be the same as the original
+conditions.
+
+B.5 : Pause autoneg only to Pause and Link autoneg transition
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Goal: Validate that drivers store the user intent in the pause rx/tx attributes
+when disabling link autoneg, but *keeping the pause autoneg enabled*.
+
+When pause autoneg is enabled, the rx and tx pause parameters are the user intent,
+but can be different to the actual pause parameters actively in use.
+
+Test scenario:
+--------------
+
+ - Configure rx and tx pause parameters to **on** and pause autoneg to **on**::
+
+ ethtool -A <iface> autoneg on rx on tx on
+
+ - Disable link autonegotiation::
+
+ ethtool -s <iface> autoneg off
+
+ - Configure rx and tx pause to **rx off**, **tx on** and autoneg to **on**::
+
+ ethtool -A <iface> autoneg on rx off tx on
+
+ - No change in the pause parameters should occur
+ - Re-enable link negotiation::
+
+ ethtool -s <iface> autoneg on
+
+ - Link must now re-negotiate pause to **rx off** and **tx on**::
+
+ ethtool -a <iface>
+
+ Pause parameters for <iface>:
+ Autonegotiate: on
+ RX: off
+ TX: on
+ RX negotiated: off
+ TX negotiated: on
+
--
2.54.0
^ permalink raw reply related
* [PATCH] arm64: Document SVE constraints on new hwcaps
From: Mark Brown @ 2026-05-22 17:50 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Jonathan Corbet, Shuah Khan
Cc: linux-arm-kernel, linux-doc, linux-kernel, Mark Brown
Two of the SVE hwcaps added for the SVE features in the 2025 dpISA did
not explicitly call out their dependency on SVE in the ABI documentation.
Do so.
While we're here reorder the SVE and fature specific ID registers for
HWCAP3_SVE_LUT6 which did have the SVE dependency but listed it second
unlike the other SVE specific ID registers.
Fixes: abca5e69ab626 ("arm64/cpufeature: Define hwcaps for 2025 dpISA features")
Reported-by: Will Deacon <will@kernel.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Documentation/arch/arm64/elf_hwcaps.rst | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/Documentation/arch/arm64/elf_hwcaps.rst b/Documentation/arch/arm64/elf_hwcaps.rst
index 07ff9ea1d605..f60ca5612daa 100644
--- a/Documentation/arch/arm64/elf_hwcaps.rst
+++ b/Documentation/arch/arm64/elf_hwcaps.rst
@@ -452,10 +452,12 @@ HWCAP3_LS64
memory location, otherwise fallback to the non-atomic alternatives.
HWCAP3_SVE_B16MM
- Functionality implied by ID_AA64ZFR0_EL1.B16B16 == 0b0011
+ Functionality implied by ID_AA64PFR0_EL1.SVE == 0b0001 and
+ ID_AA64ZFR0_EL1.B16B16 == 0b0011
HWCAP3_SVE2P3
- Functionality implied by ID_AA64ZFR0_EL1.SVEver == 0b0100
+ Functionality implied by ID_AA64PFR0_EL1.SVE == 0b0001 and
+ ID_AA64ZFR0_EL1.SVEver == 0b0100
HWCAP3_SME_LUT6
Functionality implied by ID_AA64SMFR0_EL1.LUT6 == 0b1
@@ -473,8 +475,9 @@ HWCAP3_F16F32MM
Functionality implied by ID_AA64ISAR0_EL1.FHM == 0b0011
HWCAP3_SVE_LUT6
- Functionality implied by ID_AA64ISAR2_EL1.LUT == 0b0010 and
- ID_AA64PFR0_EL1.SVE == 0b0001.
+ Functionality implied by ID_AA64PFR0_EL1.SVE == 0b0001 and
+ ID_AA64ISAR2_EL1.LUT == 0b0010.
+
4. Unused AT_HWCAP bits
-----------------------
---
base-commit: abca5e69ab6268cbe1913b19da5a98c3383f8bb3
change-id: 20260522-arm64-elf-hwcaps-sve-cleanup-1af7874ad5b7
Best regards,
--
Mark Brown <broonie@kernel.org>
^ permalink raw reply related
* Re: [PATCH v4 27/30] KVM: x86: Add KVM_VCPU_TSC_EFFECTIVE_FREQ attribute
From: David Woodhouse @ 2026-05-22 17:48 UTC (permalink / raw)
To: Sean Christopherson
Cc: Paolo Bonzini, Jonathan Corbet, Shuah Khan, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
Vitaly Kuznetsov, Juergen Gross, Boris Ostrovsky, Paul Durrant,
Jonathan Cameron, Sascha Bischoff, Marc Zyngier, Joey Gouly,
Jack Allister, Dongli Zhang, joe.jin, kvm, linux-doc,
linux-kernel, xen-devel, linux-kselftest
In-Reply-To: <ahCQluJj59uWlDAF@google.com>
[-- Attachment #1: Type: text/plain, Size: 287 bytes --]
On Fri, 2026-05-22 at 10:21 -0700, Sean Christopherson wrote:
>
> I'll send a standalone patch, along with a selftest tweak to verify the fix.
> It's technically a fix and won't generate any conflicts, no reason to delay it.
Are you suggesting the other 30 should be delayed? :P
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox