aboutsummaryrefslogtreecommitdiff
path: root/sys/compat
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/freebsd32/freebsd32_syscall.h4
-rw-r--r--sys/compat/freebsd32/freebsd32_syscalls.c2
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c2
-rw-r--r--sys/compat/freebsd32/freebsd32_systrace_args.c44
-rw-r--r--sys/compat/lindebugfs/lindebugfs.c8
-rw-r--r--sys/compat/linprocfs/linprocfs.c256
-rw-r--r--sys/compat/linsysfs/linsysfs.c159
-rw-r--r--sys/compat/linsysfs/linsysfs_net.c24
-rw-r--r--sys/compat/linux/linux_misc.c41
-rw-r--r--sys/compat/linux/linux_netlink.c39
-rw-r--r--sys/compat/linux/linux_socket.c12
-rw-r--r--sys/compat/linux/linux_uid16.c39
-rw-r--r--sys/compat/linuxkpi/common/include/acpi/acpi.h2
-rw-r--r--sys/compat/linuxkpi/common/include/kunit/static_stub.h15
-rw-r--r--sys/compat/linuxkpi/common/include/linux/cleanup.h49
-rw-r--r--sys/compat/linuxkpi/common/include/linux/compiler.h6
-rw-r--r--sys/compat/linuxkpi/common/include/linux/device.h5
-rw-r--r--sys/compat/linuxkpi/common/include/linux/ieee80211.h8
-rw-r--r--sys/compat/linuxkpi/common/include/linux/math.h2
-rw-r--r--sys/compat/linuxkpi/common/include/linux/math64.h6
-rw-r--r--sys/compat/linuxkpi/common/include/linux/overflow.h180
-rw-r--r--sys/compat/linuxkpi/common/include/linux/pci.h17
-rw-r--r--sys/compat/linuxkpi/common/include/linux/rcupdate.h5
-rw-r--r--sys/compat/linuxkpi/common/include/linux/skbuff.h14
-rw-r--r--sys/compat/linuxkpi/common/include/linux/slab.h4
-rw-r--r--sys/compat/linuxkpi/common/include/linux/string_choices.h71
-rw-r--r--sys/compat/linuxkpi/common/include/linux/string_helpers.h67
-rw-r--r--sys/compat/linuxkpi/common/include/linux/timer.h21
-rw-r--r--sys/compat/linuxkpi/common/include/net/mac80211.h2
-rw-r--r--sys/compat/linuxkpi/common/src/linux_80211.c108
-rw-r--r--sys/compat/linuxkpi/common/src/linux_compat.c11
-rw-r--r--sys/compat/linuxkpi/common/src/linux_devres.c26
-rw-r--r--sys/compat/linuxkpi/common/src/linux_pci.c128
-rw-r--r--sys/compat/linuxkpi/dummy/include/kunit/skbuff.h0
-rw-r--r--sys/compat/linuxkpi/dummy/include/kunit/test-bug.h0
-rw-r--r--sys/compat/linuxkpi/dummy/include/kunit/test.h0
36 files changed, 942 insertions, 435 deletions
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
index 90cd21a80923..54063150eef9 100644
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -515,4 +515,6 @@
#define FREEBSD32_SYS_inotify_rm_watch 594
#define FREEBSD32_SYS_getgroups 595
#define FREEBSD32_SYS_setgroups 596
-#define FREEBSD32_SYS_MAXSYSCALL 597
+#define FREEBSD32_SYS_jail_attach_jd 597
+#define FREEBSD32_SYS_jail_remove_jd 598
+#define FREEBSD32_SYS_MAXSYSCALL 599
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
index f0f8d26554b5..f7cc4c284e4d 100644
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -602,4 +602,6 @@ const char *freebsd32_syscallnames[] = {
"inotify_rm_watch", /* 594 = inotify_rm_watch */
"getgroups", /* 595 = getgroups */
"setgroups", /* 596 = setgroups */
+ "jail_attach_jd", /* 597 = jail_attach_jd */
+ "jail_remove_jd", /* 598 = jail_remove_jd */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
index 12f1a346c3e9..18f809ef04e3 100644
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -664,4 +664,6 @@ struct sysent freebsd32_sysent[] = {
{ .sy_narg = AS(inotify_rm_watch_args), .sy_call = (sy_call_t *)sys_inotify_rm_watch, .sy_auevent = AUE_INOTIFY, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 594 = inotify_rm_watch */
{ .sy_narg = AS(getgroups_args), .sy_call = (sy_call_t *)sys_getgroups, .sy_auevent = AUE_GETGROUPS, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 595 = getgroups */
{ .sy_narg = AS(setgroups_args), .sy_call = (sy_call_t *)sys_setgroups, .sy_auevent = AUE_SETGROUPS, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 596 = setgroups */
+ { .sy_narg = AS(jail_attach_jd_args), .sy_call = (sy_call_t *)sys_jail_attach_jd, .sy_auevent = AUE_JAIL_ATTACH, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 597 = jail_attach_jd */
+ { .sy_narg = AS(jail_remove_jd_args), .sy_call = (sy_call_t *)sys_jail_remove_jd, .sy_auevent = AUE_JAIL_REMOVE, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 598 = jail_remove_jd */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
index e471c5148021..29a5497e9efa 100644
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3413,6 +3413,20 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
*n_args = 2;
break;
}
+ /* jail_attach_jd */
+ case 597: {
+ struct jail_attach_jd_args *p = params;
+ iarg[a++] = p->fd; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* jail_remove_jd */
+ case 598: {
+ struct jail_remove_jd_args *p = params;
+ iarg[a++] = p->fd; /* int */
+ *n_args = 1;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9222,6 +9236,26 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
};
break;
+ /* jail_attach_jd */
+ case 597:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* jail_remove_jd */
+ case 598:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11130,6 +11164,16 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* jail_attach_jd */
+ case 597:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* jail_remove_jd */
+ case 598:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/compat/lindebugfs/lindebugfs.c b/sys/compat/lindebugfs/lindebugfs.c
index 50f9377ffec3..8cddc6f390bc 100644
--- a/sys/compat/lindebugfs/lindebugfs.c
+++ b/sys/compat/lindebugfs/lindebugfs.c
@@ -206,7 +206,7 @@ debugfs_create_file(const char *name, umode_t mode,
pnode = debugfs_root;
flags = fops->write ? PFS_RDWR : PFS_RD;
- dnode->d_pfs_node = pfs_create_file(pnode, name, debugfs_fill,
+ pfs_create_file(pnode, &dnode->d_pfs_node, name, debugfs_fill,
debugfs_attr, NULL, debugfs_destroy, flags | PFS_NOWAIT);
if (dnode->d_pfs_node == NULL) {
free(dm, M_DFSINT);
@@ -283,7 +283,8 @@ debugfs_create_dir(const char *name, struct dentry *parent)
else
pnode = debugfs_root;
- dnode->d_pfs_node = pfs_create_dir(pnode, name, debugfs_attr, NULL, debugfs_destroy, PFS_RD | PFS_NOWAIT);
+ pfs_create_dir(pnode, &dnode->d_pfs_node, name, debugfs_attr, NULL,
+ debugfs_destroy, PFS_RD | PFS_NOWAIT);
if (dnode->d_pfs_node == NULL) {
free(dm, M_DFSINT);
return (NULL);
@@ -316,7 +317,8 @@ debugfs_create_symlink(const char *name, struct dentry *parent,
else
pnode = debugfs_root;
- dnode->d_pfs_node = pfs_create_link(pnode, name, &debugfs_fill_data, NULL, NULL, NULL, PFS_NOWAIT);
+ pfs_create_link(pnode, &dnode->d_pfs_node, name, &debugfs_fill_data,
+ NULL, NULL, NULL, PFS_NOWAIT);
if (dnode->d_pfs_node == NULL)
goto fail;
dnode->d_pfs_node->pn_data = dm;
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 1c6d64d6b8bc..95b212be1306 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -2320,165 +2320,165 @@ linprocfs_init(PFS_INIT_ARGS)
root = pi->pi_root;
/* /proc/... */
- pfs_create_file(root, "cmdline", &linprocfs_docmdline,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "devices", &linprocfs_dodevices,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "modules", &linprocfs_domodules,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "mounts", &linprocfs_domtab,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "mtab", &linprocfs_domtab,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "partitions", &linprocfs_dopartitions,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_link(root, "self", &procfs_docurproc,
- NULL, NULL, NULL, 0);
- pfs_create_file(root, "stat", &linprocfs_dostat,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "swaps", &linprocfs_doswaps,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "uptime", &linprocfs_douptime,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(root, "version", &linprocfs_doversion,
+ pfs_create_file(root, NULL, "cmdline", &linprocfs_docmdline, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "cpuinfo", &linprocfs_docpuinfo, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "devices", &linprocfs_dodevices, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "filesystems", &linprocfs_dofilesystems,
NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, NULL, "loadavg", &linprocfs_doloadavg, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "meminfo", &linprocfs_domeminfo, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "modules", &linprocfs_domodules, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "mounts", &linprocfs_domtab, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "mtab", &linprocfs_domtab, NULL, NULL, NULL,
+ PFS_RD);
+ pfs_create_file(root, NULL, "partitions", &linprocfs_dopartitions, NULL,
+ NULL, NULL, PFS_RD);
+ pfs_create_link(root, NULL, "self", &procfs_docurproc, NULL, NULL, NULL,
+ 0);
+ pfs_create_file(root, NULL, "stat", &linprocfs_dostat, NULL, NULL, NULL,
+ PFS_RD);
+ pfs_create_file(root, NULL, "swaps", &linprocfs_doswaps, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "uptime", &linprocfs_douptime, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(root, NULL, "version", &linprocfs_doversion, NULL, NULL,
+ NULL, PFS_RD);
/* /proc/bus/... */
- dir = pfs_create_dir(root, "bus", NULL, NULL, NULL, 0);
- dir = pfs_create_dir(dir, "pci", NULL, NULL, NULL, 0);
- dir = pfs_create_dir(dir, "devices", NULL, NULL, NULL, 0);
+ pfs_create_dir(root, &dir, "bus", NULL, NULL, NULL, 0);
+ pfs_create_dir(dir, &dir, "pci", NULL, NULL, NULL, 0);
+ pfs_create_dir(dir, &dir, "devices", NULL, NULL, NULL, 0);
/* /proc/net/... */
- dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
- pfs_create_file(dir, "dev", &linprocfs_donetdev,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "route", &linprocfs_donetroute,
- NULL, NULL, NULL, PFS_RD);
+ pfs_create_dir(root, &dir, "net", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, "dev", &linprocfs_donetdev, NULL, NULL, NULL,
+ PFS_RD);
+ pfs_create_file(dir, NULL, "route", &linprocfs_donetroute, NULL, NULL,
+ NULL, PFS_RD);
/* /proc/<pid>/... */
- dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
- pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
- NULL, NULL, NULL, 0);
- pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
- NULL, &procfs_candebug, NULL, PFS_RD);
- pfs_create_link(dir, "exe", &procfs_doprocfile,
- NULL, &procfs_notsystem, NULL, 0);
- pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
- NULL, NULL, NULL, PFS_RD | PFS_AUTODRAIN);
- pfs_create_file(dir, "mem", &linprocfs_doprocmem,
- procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR | PFS_RAW);
- pfs_create_file(dir, "mountinfo", &linprocfs_doprocmountinfo,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "mounts", &linprocfs_domtab,
+ pfs_create_dir(root, &dir, "pid", NULL, NULL, NULL, PFS_PROCDEP);
+ pfs_create_file(dir, NULL, "cmdline", &linprocfs_doproccmdline, NULL,
+ NULL, NULL, PFS_RD);
+ pfs_create_link(dir, NULL, "cwd", &linprocfs_doproccwd, NULL, NULL,
+ NULL, 0);
+ pfs_create_file(dir, NULL, "environ", &linprocfs_doprocenviron, NULL,
+ &procfs_candebug, NULL, PFS_RD);
+ pfs_create_link(dir, NULL, "exe", &procfs_doprocfile, NULL,
+ &procfs_notsystem, NULL, 0);
+ pfs_create_file(dir, NULL, "maps", &linprocfs_doprocmaps, NULL, NULL,
+ NULL, PFS_RD | PFS_AUTODRAIN);
+ pfs_create_file(dir, NULL, "mem", &linprocfs_doprocmem, procfs_attr_rw,
+ &procfs_candebug, NULL, PFS_RDWR | PFS_RAW);
+ pfs_create_file(dir, NULL, "mountinfo", &linprocfs_doprocmountinfo,
NULL, NULL, NULL, PFS_RD);
- pfs_create_link(dir, "root", &linprocfs_doprocroot,
- NULL, NULL, NULL, 0);
- pfs_create_file(dir, "stat", &linprocfs_doprocstat,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "status", &linprocfs_doprocstatus,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
- NULL, NULL, NULL, 0);
- pfs_create_file(dir, "auxv", &linprocfs_doauxv,
- NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
- pfs_create_file(dir, "limits", &linprocfs_doproclimits,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "oom_score_adj", &linprocfs_do_oom_score_adj,
+ pfs_create_file(dir, NULL, "mounts", &linprocfs_domtab, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_link(dir, NULL, "root", &linprocfs_doprocroot, NULL, NULL,
+ NULL, 0);
+ pfs_create_file(dir, NULL, "stat", &linprocfs_doprocstat, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "statm", &linprocfs_doprocstatm, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "status", &linprocfs_doprocstatus, NULL,
+ NULL, NULL, PFS_RD);
+ pfs_create_link(dir, NULL, "fd", &linprocfs_dofdescfs, NULL, NULL, NULL,
+ 0);
+ pfs_create_file(dir, NULL, "auxv", &linprocfs_doauxv, NULL,
+ &procfs_candebug, NULL, PFS_RD | PFS_RAWRD);
+ pfs_create_file(dir, NULL, "limits", &linprocfs_doproclimits, NULL,
+ NULL, NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "oom_score_adj", &linprocfs_do_oom_score_adj,
procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR);
/* /proc/<pid>/task/... */
- dir = pfs_create_dir(dir, "task", linprocfs_dotaskattr, NULL, NULL, 0);
- pfs_create_file(dir, ".dummy", &linprocfs_dotaskdummy,
- NULL, NULL, NULL, PFS_RD);
+ pfs_create_dir(dir, &dir, "task", linprocfs_dotaskattr, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, ".dummy", &linprocfs_dotaskdummy, NULL, NULL,
+ NULL, PFS_RD);
/* /proc/scsi/... */
- dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
- pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
+ pfs_create_dir(root, &dir, "scsi", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, "device_info", &linprocfs_doscsidevinfo,
NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "scsi", &linprocfs_doscsiscsi, NULL, NULL,
+ NULL, PFS_RD);
/* /proc/sys/... */
- sys = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
+ pfs_create_dir(root, &sys, "sys", NULL, NULL, NULL, 0);
/* /proc/sys/kernel/... */
- dir = pfs_create_dir(sys, "kernel", NULL, NULL, NULL, 0);
- pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "ostype", &linprocfs_doostype,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "version", &linprocfs_doosbuild,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "msgmax", &linprocfs_domsgmax,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "msgmnb", &linprocfs_domsgmnb,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "ngroups_max", &linprocfs_dongroups_max,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "sem", &linprocfs_dosem,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "shmall", &linprocfs_doshmall,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "shmmax", &linprocfs_doshmmax,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "shmmni", &linprocfs_doshmmni,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "tainted", &linprocfs_dotainted,
+ pfs_create_dir(sys, &dir, "kernel", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, "osrelease", &linprocfs_doosrelease, NULL,
+ NULL, NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "ostype", &linprocfs_doostype, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "version", &linprocfs_doosbuild, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "msgmax", &linprocfs_domsgmax, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "msgmni", &linprocfs_domsgmni, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "msgmnb", &linprocfs_domsgmnb, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "ngroups_max", &linprocfs_dongroups_max,
NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "pid_max", &linprocfs_dopid_max, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "sem", &linprocfs_dosem, NULL, NULL, NULL,
+ PFS_RD);
+ pfs_create_file(dir, NULL, "shmall", &linprocfs_doshmall, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "shmmax", &linprocfs_doshmmax, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "shmmni", &linprocfs_doshmmni, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "tainted", &linprocfs_dotainted, NULL, NULL,
+ NULL, PFS_RD);
/* /proc/sys/kernel/random/... */
- dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
- pfs_create_file(dir, "uuid", &linprocfs_douuid,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "boot_id", &linprocfs_doboot_id,
- NULL, NULL, NULL, PFS_RD);
+ pfs_create_dir(dir, &dir, "random", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, "uuid", &linprocfs_douuid, NULL, NULL, NULL,
+ PFS_RD);
+ pfs_create_file(dir, NULL, "boot_id", &linprocfs_doboot_id, NULL, NULL,
+ NULL, PFS_RD);
/* /proc/sys/vm/.... */
- dir = pfs_create_dir(sys, "vm", NULL, NULL, NULL, 0);
- pfs_create_file(dir, "min_free_kbytes", &linprocfs_dominfree,
+ pfs_create_dir(sys, &dir, "vm", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, "min_free_kbytes", &linprocfs_dominfree,
NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "max_map_count", &linprocfs_domax_map_cnt,
+ pfs_create_file(dir, NULL, "max_map_count", &linprocfs_domax_map_cnt,
NULL, NULL, NULL, PFS_RD);
/* /proc/sysvipc/... */
- dir = pfs_create_dir(root, "sysvipc", NULL, NULL, NULL, 0);
- pfs_create_file(dir, "msg", &linprocfs_dosysvipc_msg,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "sem", &linprocfs_dosysvipc_sem,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "shm", &linprocfs_dosysvipc_shm,
- NULL, NULL, NULL, PFS_RD);
+ pfs_create_dir(root, &dir, "sysvipc", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, "msg", &linprocfs_dosysvipc_msg, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "sem", &linprocfs_dosysvipc_sem, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "shm", &linprocfs_dosysvipc_shm, NULL, NULL,
+ NULL, PFS_RD);
/* /proc/sys/fs/... */
- dir = pfs_create_dir(sys, "fs", NULL, NULL, NULL, 0);
+ pfs_create_dir(sys, &dir, "fs", NULL, NULL, NULL, 0);
/* /proc/sys/fs/mqueue/... */
- dir = pfs_create_dir(dir, "mqueue", NULL, NULL, NULL, 0);
- pfs_create_file(dir, "msg_default", &linprocfs_domqueue_msg_default,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "msgsize_default", &linprocfs_domqueue_msgsize_default,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "msg_max", &linprocfs_domqueue_msg_max,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "msgsize_max", &linprocfs_domqueue_msgsize_max,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(dir, "queues_max", &linprocfs_domqueue_queues_max,
+ pfs_create_dir(dir, &dir, "mqueue", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, NULL, "msg_default",
+ &linprocfs_domqueue_msg_default, NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "msgsize_default",
+ &linprocfs_domqueue_msgsize_default, NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "msg_max", &linprocfs_domqueue_msg_max, NULL,
+ NULL, NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "msgsize_max",
+ &linprocfs_domqueue_msgsize_max, NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, NULL, "queues_max", &linprocfs_domqueue_queues_max,
NULL, NULL, NULL, PFS_RD);
return (0);
diff --git a/sys/compat/linsysfs/linsysfs.c b/sys/compat/linsysfs/linsysfs.c
index 7f70221b420d..5a41c5193415 100644
--- a/sys/compat/linsysfs/linsysfs.c
+++ b/sys/compat/linsysfs/linsysfs.c
@@ -267,6 +267,8 @@ linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi,
struct pci_devinfo *dinfo;
char *device, *host, *new_path, *devname;
+ children = NULL;
+ device = host = NULL;
new_path = path;
devname = malloc(16, M_TEMP, M_WAITOK);
@@ -292,39 +294,43 @@ linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi,
dinfo->cfg.func);
strcat(new_path, "/");
strcat(new_path, device);
- dir = pfs_create_dir(dir, device,
+ error = pfs_create_dir(dir, &dir, device,
NULL, NULL, NULL, 0);
- cur_file = pfs_create_file(dir, "vendor",
+ if (error != 0)
+ goto out;
+ pfs_create_dir(dir, &dir, device, NULL, NULL,
+ NULL, 0);
+ pfs_create_file(dir, &cur_file, "vendor",
&linsysfs_fill_vendor, NULL, NULL, NULL,
PFS_RD);
cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir, "device",
+ pfs_create_file(dir, &cur_file, "device",
&linsysfs_fill_device, NULL, NULL, NULL,
PFS_RD);
cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir,
+ pfs_create_file(dir, &cur_file,
"subsystem_vendor",
&linsysfs_fill_subvendor, NULL, NULL, NULL,
PFS_RD);
cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir,
+ pfs_create_file(dir, &cur_file,
"subsystem_device",
&linsysfs_fill_subdevice, NULL, NULL, NULL,
PFS_RD);
cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir, "revision",
+ pfs_create_file(dir, &cur_file, "revision",
&linsysfs_fill_revid, NULL, NULL, NULL,
PFS_RD);
cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir, "config",
+ pfs_create_file(dir, &cur_file, "config",
&linsysfs_fill_config, NULL, NULL, NULL,
PFS_RD);
cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_file(dir, "uevent",
- &linsysfs_fill_uevent_pci, NULL, NULL,
- NULL, PFS_RD);
+ pfs_create_file(dir, &cur_file, "uevent",
+ &linsysfs_fill_uevent_pci, NULL, NULL, NULL,
+ PFS_RD);
cur_file->pn_data = (void*)dev;
- cur_file = pfs_create_link(dir, "subsystem",
+ pfs_create_link(dir, &cur_file, "subsystem",
&linsysfs_fill_data, NULL, NULL, NULL, 0);
/* libdrm just checks that the link ends in "/pci" */
cur_file->pn_data = "/sys/bus/pci";
@@ -334,34 +340,32 @@ linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi,
sprintf(host, "host%d", host_number++);
strcat(new_path, "/");
strcat(new_path, host);
- pfs_create_dir(dir, host,
- NULL, NULL, NULL, 0);
+ pfs_create_dir(dir, NULL, host, NULL,
+ NULL, NULL, 0);
scsi_host = malloc(sizeof(
struct scsi_host_queue),
- M_DEVBUF, M_NOWAIT);
+ M_DEVBUF, M_WAITOK);
scsi_host->path = malloc(
strlen(new_path) + 1,
- M_DEVBUF, M_NOWAIT);
+ M_DEVBUF, M_WAITOK);
scsi_host->path[0] = '\000';
bcopy(new_path, scsi_host->path,
strlen(new_path) + 1);
scsi_host->name = "unknown";
- sub_dir = pfs_create_dir(scsi, host,
+ pfs_create_dir(scsi, &sub_dir, host,
NULL, NULL, NULL, 0);
- pfs_create_link(sub_dir, "device",
- &linsysfs_link_scsi_host,
- NULL, NULL, NULL, 0);
- pfs_create_file(sub_dir, "proc_name",
- &linsysfs_scsiname,
+ pfs_create_link(sub_dir, NULL, "device",
+ &linsysfs_link_scsi_host, NULL,
+ NULL, NULL, 0);
+ pfs_create_file(sub_dir, NULL,
+ "proc_name", &linsysfs_scsiname,
NULL, NULL, NULL, PFS_RD);
scsi_host->name
= linux_driver_get_name_dev(dev);
TAILQ_INSERT_TAIL(&scsi_host_q,
scsi_host, scsi_host_next);
}
- free(device, M_TEMP);
- free(host, M_TEMP);
}
}
@@ -374,26 +378,27 @@ linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi,
device_get_unit(dev) >= 0) {
dinfo = device_get_ivars(parent);
if (dinfo != NULL && dinfo->cfg.baseclass == PCIC_DISPLAY) {
- pfs_create_dir(dir, "drm", NULL, NULL, NULL, 0);
+ pfs_create_dir(dir, NULL, "drm", NULL, NULL,
+ NULL, 0);
sprintf(devname, "226:%d",
device_get_unit(dev));
- sub_dir = pfs_create_dir(chardev,
- devname, NULL, NULL, NULL, 0);
- cur_file = pfs_create_link(sub_dir,
- "device", &linsysfs_fill_vgapci, NULL,
- NULL, NULL, PFS_RD);
+ pfs_create_dir(chardev, &sub_dir, devname, NULL,
+ NULL, NULL, 0);
+ pfs_create_link(sub_dir, &cur_file, "device",
+ &linsysfs_fill_vgapci, NULL, NULL, NULL,
+ PFS_RD);
cur_file->pn_data = (void*)dir;
- cur_file = pfs_create_file(sub_dir,
- "uevent", &linsysfs_fill_uevent_drm, NULL,
- NULL, NULL, PFS_RD);
+ pfs_create_file(sub_dir, &cur_file, "uevent",
+ &linsysfs_fill_uevent_drm, NULL, NULL, NULL,
+ PFS_RD);
cur_file->pn_data = (void*)dev;
sprintf(devname, "card%d",
device_get_unit(dev));
- sub_dir = pfs_create_dir(drm,
- devname, NULL, NULL, NULL, 0);
- cur_file = pfs_create_link(sub_dir,
- "device", &linsysfs_fill_vgapci, NULL,
- NULL, NULL, PFS_RD);
+ pfs_create_dir(drm, &sub_dir, devname, NULL,
+ NULL, NULL, 0);
+ pfs_create_link(sub_dir, &cur_file, "device",
+ &linsysfs_fill_vgapci, NULL, NULL, NULL,
+ PFS_RD);
cur_file->pn_data = (void*)dir;
}
}
@@ -401,17 +406,37 @@ linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi,
error = device_get_children(dev, &children, &nchildren);
if (error == 0) {
- for (i = 0; i < nchildren; i++)
- if (children[i])
- linsysfs_run_bus(children[i], dir, scsi,
+ for (i = 0; i < nchildren; i++) {
+ if (children[i]) {
+ error = linsysfs_run_bus(children[i], dir, scsi,
chardev, drm, new_path, prefix);
- free(children, M_TEMP);
+ if (error != 0) {
+ printf(
+ "linsysfs_run_bus: %s omitted from sysfs tree, error %d\n",
+ device_get_nameunit(children[i]),
+ error);
+ }
+ }
+ }
+
+ /*
+ * We override the error to avoid cascading failures; the
+ * innermost device that failed in a tree is probably the most
+ * significant one for diagnostics, its parents would be noise.
+ */
+ error = 0;
}
+
+out:
+ free(host, M_TEMP);
+ free(device, M_TEMP);
+ if (children != NULL)
+ free(children, M_TEMP);
if (new_path != path)
free(new_path, M_TEMP);
free(devname, M_TEMP);
- return (1);
+ return (error);
}
/*
@@ -455,10 +480,10 @@ linsysfs_listcpus(struct pfs_node *dir)
for (i = 0; i < mp_ncpus; ++i) {
/* /sys/devices/system/cpu/cpuX */
sprintf(name, "cpu%d", i);
- cpu = pfs_create_dir(dir, name, NULL, NULL, NULL, 0);
+ pfs_create_dir(dir, &cpu, name, NULL, NULL, NULL, 0);
- pfs_create_file(cpu, "online", &linsysfs_cpuxonline,
- NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(cpu, NULL, "online", &linsysfs_cpuxonline, NULL,
+ NULL, NULL, PFS_RD);
}
free(name, M_TEMP);
}
@@ -485,52 +510,56 @@ linsysfs_init(PFS_INIT_ARGS)
root = pi->pi_root;
/* /sys/bus/... */
- dir = pfs_create_dir(root, "bus", NULL, NULL, NULL, 0);
+ pfs_create_dir(root, &dir, "bus", NULL, NULL, NULL, 0);
/* /sys/class/... */
- class = pfs_create_dir(root, "class", NULL, NULL, NULL, 0);
- scsi = pfs_create_dir(class, "scsi_host", NULL, NULL, NULL, 0);
- drm = pfs_create_dir(class, "drm", NULL, NULL, NULL, 0);
- pfs_create_dir(class, "power_supply", NULL, NULL, NULL, 0);
+ pfs_create_dir(root, &class, "class", NULL, NULL, NULL, 0);
+ pfs_create_dir(class, &scsi, "scsi_host", NULL, NULL, NULL, 0);
+ pfs_create_dir(class, &drm, "drm", NULL, NULL, NULL, 0);
+ pfs_create_dir(class, NULL, "power_supply", NULL, NULL, NULL, 0);
/* /sys/class/net/.. */
- net = pfs_create_dir(class, "net", NULL, NULL, NULL, 0);
+ pfs_create_dir(class, &net, "net", NULL, NULL, NULL, 0);
/* /sys/dev/... */
- devdir = pfs_create_dir(root, "dev", NULL, NULL, NULL, 0);
- chardev = pfs_create_dir(devdir, "char", NULL, NULL, NULL, 0);
+ pfs_create_dir(root, &devdir, "dev", NULL, NULL, NULL, 0);
+ pfs_create_dir(devdir, &chardev, "char", NULL, NULL, NULL, 0);
/* /sys/devices/... */
- dir = pfs_create_dir(root, "devices", NULL, NULL, NULL, 0);
- pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, NULL, 0);
+ pfs_create_dir(root, &dir, "devices", NULL, NULL, NULL, 0);
+ pfs_create_dir(dir, &pci, "pci0000:00", NULL, NULL, NULL, 0);
devclass = devclass_find("root");
if (devclass == NULL) {
return (0);
}
+ /*
+ * This assumes that the root node is unlikely to error out in
+ * linsysfs_run_bus, which may or may not be true.
+ */
dev = devclass_get_device(devclass, 0);
linsysfs_run_bus(dev, pci, scsi, chardev, drm, "/pci0000:00", "0000");
/* /sys/devices/system */
- sys = pfs_create_dir(dir, "system", NULL, NULL, NULL, 0);
+ pfs_create_dir(dir, &sys, "system", NULL, NULL, NULL, 0);
/* /sys/devices/system/cpu */
- cpu = pfs_create_dir(sys, "cpu", NULL, NULL, NULL, 0);
+ pfs_create_dir(sys, &cpu, "cpu", NULL, NULL, NULL, 0);
- pfs_create_file(cpu, "online", &linsysfs_cpuonline,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(cpu, "possible", &linsysfs_cpuonline,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(cpu, "present", &linsysfs_cpuonline,
- NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(cpu, NULL, "online", &linsysfs_cpuonline, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(cpu, NULL, "possible", &linsysfs_cpuonline, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(cpu, NULL, "present", &linsysfs_cpuonline, NULL, NULL,
+ NULL, PFS_RD);
linsysfs_listcpus(cpu);
/* /sys/kernel */
- kernel = pfs_create_dir(root, "kernel", NULL, NULL, NULL, 0);
+ pfs_create_dir(root, &kernel, "kernel", NULL, NULL, NULL, 0);
/* /sys/kernel/debug, mountpoint for lindebugfs. */
- pfs_create_dir(kernel, "debug", NULL, NULL, NULL, 0);
+ pfs_create_dir(kernel, NULL, "debug", NULL, NULL, NULL, 0);
linsysfs_net_init();
diff --git a/sys/compat/linsysfs/linsysfs_net.c b/sys/compat/linsysfs/linsysfs_net.c
index 73602b0132a4..751dbb5b3713 100644
--- a/sys/compat/linsysfs/linsysfs_net.c
+++ b/sys/compat/linsysfs/linsysfs_net.c
@@ -237,22 +237,22 @@ linsysfs_net_addif(if_t ifp, void *arg)
nic = pfs_find_node(dir, ifname);
if (nic == NULL) {
- nic = pfs_create_dir(dir, ifname, NULL, linsysfs_if_visible,
+ pfs_create_dir(dir, &nic, ifname, NULL, linsysfs_if_visible,
NULL, 0);
- pfs_create_file(nic, "address", &linsysfs_if_addr,
+ pfs_create_file(nic, NULL, "address", &linsysfs_if_addr, NULL,
+ NULL, NULL, PFS_RD);
+ pfs_create_file(nic, NULL, "addr_len", &linsysfs_if_addrlen,
NULL, NULL, NULL, PFS_RD);
- pfs_create_file(nic, "addr_len", &linsysfs_if_addrlen,
+ pfs_create_file(nic, NULL, "flags", &linsysfs_if_flags, NULL,
+ NULL, NULL, PFS_RD);
+ pfs_create_file(nic, NULL, "ifindex", &linsysfs_if_ifindex,
NULL, NULL, NULL, PFS_RD);
- pfs_create_file(nic, "flags", &linsysfs_if_flags,
+ pfs_create_file(nic, NULL, "mtu", &linsysfs_if_mtu, NULL, NULL,
+ NULL, PFS_RD);
+ pfs_create_file(nic, NULL, "tx_queue_len", &linsysfs_if_txq_len,
NULL, NULL, NULL, PFS_RD);
- pfs_create_file(nic, "ifindex", &linsysfs_if_ifindex,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(nic, "mtu", &linsysfs_if_mtu,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(nic, "tx_queue_len", &linsysfs_if_txq_len,
- NULL, NULL, NULL, PFS_RD);
- pfs_create_file(nic, "type", &linsysfs_if_type,
- NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(nic, NULL, "type", &linsysfs_if_type, NULL,
+ NULL, NULL, PFS_RD);
}
/*
* There is a small window between registering the if_arrival
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 5e32353c6b8e..0925ffb64480 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1028,24 +1028,24 @@ linux_nice(struct thread *td, struct linux_nice_args *args)
int
linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
{
+ const int ngrp = args->gidsetsize;
struct ucred *newcred, *oldcred;
l_gid_t *linux_gidset;
- int ngrp, error;
+ int error;
struct proc *p;
- ngrp = args->gidsetsize;
- if (ngrp < 0 || ngrp >= ngroups_max)
+ if (ngrp < 0 || ngrp > ngroups_max)
return (EINVAL);
linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t));
if (error)
goto out;
+
newcred = crget();
crextend(newcred, ngrp);
p = td->td_proc;
PROC_LOCK(p);
- oldcred = p->p_ucred;
- crcopy(newcred, oldcred);
+ oldcred = crcopysafe(p, newcred);
if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS)) != 0) {
PROC_UNLOCK(p);
@@ -1071,34 +1071,29 @@ out:
int
linux_getgroups(struct thread *td, struct linux_getgroups_args *args)
{
- struct ucred *cred;
+ const struct ucred *const cred = td->td_ucred;
l_gid_t *linux_gidset;
- gid_t *bsd_gidset;
- int bsd_gidsetsz, ngrp, error;
+ int ngrp, error;
- cred = td->td_ucred;
- bsd_gidset = cred->cr_groups;
- bsd_gidsetsz = cred->cr_ngroups;
+ ngrp = args->gidsetsize;
- if ((ngrp = args->gidsetsize) == 0) {
- td->td_retval[0] = bsd_gidsetsz;
+ if (ngrp == 0) {
+ td->td_retval[0] = cred->cr_ngroups;
return (0);
}
-
- if (ngrp < bsd_gidsetsz)
+ if (ngrp < cred->cr_ngroups)
return (EINVAL);
- ngrp = 0;
- linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset),
- M_LINUX, M_WAITOK);
- while (ngrp < bsd_gidsetsz) {
- linux_gidset[ngrp] = bsd_gidset[ngrp];
- ngrp++;
- }
+ ngrp = cred->cr_ngroups;
+
+ linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
+ for (int i = 0; i < ngrp; ++i)
+ linux_gidset[i] = cred->cr_groups[i];
error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t));
free(linux_gidset, M_LINUX);
- if (error)
+
+ if (error != 0)
return (error);
td->td_retval[0] = ngrp;
diff --git a/sys/compat/linux/linux_netlink.c b/sys/compat/linux/linux_netlink.c
index 927f3689e2b6..6aeafe84adc6 100644
--- a/sys/compat/linux/linux_netlink.c
+++ b/sys/compat/linux/linux_netlink.c
@@ -242,9 +242,24 @@ nlmsg_copy_nla(const struct nlattr *nla_orig, struct nl_writer *nw)
}
/*
+ * Translate a FreeBSD interface name to a Linux interface name.
+ */
+static bool
+nlmsg_translate_ifname_nla(struct nlattr *nla, struct nl_writer *nw)
+{
+ char ifname[LINUX_IFNAMSIZ];
+
+ if (ifname_bsd_to_linux_name((char *)(nla + 1), ifname,
+ sizeof(ifname)) <= 0)
+ return (false);
+ return (nlattr_add_string(nw, IFLA_IFNAME, ifname));
+}
+
+#define LINUX_NLA_UNHANDLED -1
+/*
* Translate a FreeBSD attribute to a Linux attribute.
- * Returns false when the attribute is not processed and the caller must take
- * care of it.
+ * Returns LINUX_NLA_UNHANDLED when the attribute is not processed
+ * and the caller must take care of it, otherwise the result is returned.
*/
static int
nlmsg_translate_all_nla(struct nlmsghdr *hdr, struct nlattr *nla,
@@ -256,27 +271,22 @@ nlmsg_translate_all_nla(struct nlmsghdr *hdr, struct nlattr *nla,
case NL_RTM_DELLINK:
case NL_RTM_GETLINK:
switch (nla->nla_type) {
- case IFLA_IFNAME: {
- char ifname[LINUX_IFNAMSIZ];
-
- if (ifname_bsd_to_linux_name((char *)(nla + 1), ifname,
- sizeof(ifname)) > 0)
- return (true);
- break;
- }
+ case IFLA_IFNAME:
+ return (nlmsg_translate_ifname_nla(nla, nw));
default:
break;
}
default:
break;
}
- return (false);
+ return (LINUX_NLA_UNHANDLED);
}
static bool
nlmsg_copy_all_nla(struct nlmsghdr *hdr, int raw_hdrlen, struct nl_writer *nw)
{
struct nlattr *nla;
+ int ret;
int hdrlen = NETLINK_ALIGN(raw_hdrlen);
int attrs_len = hdr->nlmsg_len - sizeof(struct nlmsghdr) - hdrlen;
@@ -287,12 +297,15 @@ nlmsg_copy_all_nla(struct nlmsghdr *hdr, int raw_hdrlen, struct nl_writer *nw)
if (nla->nla_len < sizeof(struct nlattr)) {
return (false);
}
- if (!nlmsg_translate_all_nla(hdr, nla, nw) &&
- !nlmsg_copy_nla(nla, nw))
+ ret = nlmsg_translate_all_nla(hdr, nla, nw);
+ if (ret == LINUX_NLA_UNHANDLED)
+ ret = nlmsg_copy_nla(nla, nw);
+ if (!ret)
return (false);
}
return (true);
}
+#undef LINUX_NLA_UNHANDLED
static unsigned int
rtnl_if_flags_to_linux(unsigned int if_flags)
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 539d153431c4..0e07b0a60ced 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -2179,6 +2179,7 @@ static int
linux_getsockopt_so_peergroups(struct thread *td,
struct linux_getsockopt_args *args)
{
+ l_gid_t *out = PTRIN(args->optval);
struct xucred xu;
socklen_t xulen, len;
int error, i;
@@ -2197,13 +2198,12 @@ linux_getsockopt_so_peergroups(struct thread *td,
return (error);
}
- /*
- * "- 1" to skip the primary group.
- */
+ /* "- 1" to skip the primary group. */
for (i = 0; i < xu.cr_ngroups - 1; i++) {
- error = copyout(xu.cr_groups + i + 1,
- (void *)(args->optval + i * sizeof(l_gid_t)),
- sizeof(l_gid_t));
+ /* Copy to cope with a possible type discrepancy. */
+ const l_gid_t g = xu.cr_groups[i + 1];
+
+ error = copyout(&g, out + i, sizeof(l_gid_t));
if (error != 0)
return (error);
}
diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c
index 1d9a19916412..8ac093e004d0 100644
--- a/sys/compat/linux/linux_uid16.c
+++ b/sys/compat/linux/linux_uid16.c
@@ -85,13 +85,13 @@ linux_lchown16(struct thread *td, struct linux_lchown16_args *args)
int
linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args)
{
+ const int ngrp = args->gidsetsize;
struct ucred *newcred, *oldcred;
l_gid16_t *linux_gidset;
- int ngrp, error;
+ int error;
struct proc *p;
- ngrp = args->gidsetsize;
- if (ngrp < 0 || ngrp >= ngroups_max)
+ if (ngrp < 0 || ngrp > ngroups_max)
return (EINVAL);
linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
error = copyin(args->gidset, linux_gidset, ngrp * sizeof(l_gid16_t));
@@ -100,7 +100,9 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args)
free(linux_gidset, M_LINUX);
return (error);
}
+
newcred = crget();
+ crextend(newcred, ngrp);
p = td->td_proc;
PROC_LOCK(p);
oldcred = crcopysafe(p, newcred);
@@ -133,34 +135,29 @@ out:
int
linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args)
{
- struct ucred *cred;
+ const struct ucred *const cred = td->td_ucred;
l_gid16_t *linux_gidset;
- gid_t *bsd_gidset;
- int bsd_gidsetsz, ngrp, error;
+ int ngrp, error;
- cred = td->td_ucred;
- bsd_gidset = cred->cr_groups;
- bsd_gidsetsz = cred->cr_ngroups;
+ ngrp = args->gidsetsize;
- if ((ngrp = args->gidsetsize) == 0) {
- td->td_retval[0] = bsd_gidsetsz;
+ if (ngrp == 0) {
+ td->td_retval[0] = cred->cr_ngroups;
return (0);
}
-
- if (ngrp < bsd_gidsetsz)
+ if (ngrp < cred->cr_ngroups)
return (EINVAL);
- ngrp = 0;
- linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset),
- M_LINUX, M_WAITOK);
- while (ngrp < bsd_gidsetsz) {
- linux_gidset[ngrp] = bsd_gidset[ngrp];
- ngrp++;
- }
+ ngrp = cred->cr_ngroups;
+
+ linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_LINUX, M_WAITOK);
+ for (int i = 0; i < ngrp; ++i)
+ linux_gidset[i] = cred->cr_groups[i];
error = copyout(linux_gidset, args->gidset, ngrp * sizeof(l_gid16_t));
free(linux_gidset, M_LINUX);
- if (error) {
+
+ if (error != 0) {
LIN_SDT_PROBE1(uid16, linux_getgroups16, copyout_error, error);
return (error);
}
diff --git a/sys/compat/linuxkpi/common/include/acpi/acpi.h b/sys/compat/linuxkpi/common/include/acpi/acpi.h
index 016c7ede0f6e..9bb435591daa 100644
--- a/sys/compat/linuxkpi/common/include/acpi/acpi.h
+++ b/sys/compat/linuxkpi/common/include/acpi/acpi.h
@@ -131,7 +131,7 @@ acpi_format_exception(ACPI_STATUS Exception)
}
static inline ACPI_STATUS
-acpi_get_handle(ACPI_HANDLE Parent, ACPI_STRING Pathname,
+acpi_get_handle(ACPI_HANDLE Parent, const char *Pathname,
ACPI_HANDLE *RetHandle)
{
return (AcpiGetHandle(Parent, Pathname, RetHandle));
diff --git a/sys/compat/linuxkpi/common/include/kunit/static_stub.h b/sys/compat/linuxkpi/common/include/kunit/static_stub.h
new file mode 100644
index 000000000000..9d425d46dbb0
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/kunit/static_stub.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2025 The FreeBSD Foundation
+ *
+ * This software was developed by Björn Zeeb under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _LINUXKPI_KUNIT_STATIC_STUB_H
+#define _LINUXKPI_KUNIT_STATIC_STUB_H
+
+#define KUNIT_STATIC_STUB_REDIRECT(_fn, ...) do { } while(0)
+
+#endif /* _LINUXKPI_KUNIT_STATIC_STUB_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/cleanup.h b/sys/compat/linuxkpi/common/include/linux/cleanup.h
index 01f234f0cbe7..5bb146f082ed 100644
--- a/sys/compat/linuxkpi/common/include/linux/cleanup.h
+++ b/sys/compat/linuxkpi/common/include/linux/cleanup.h
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2024 The FreeBSD Foundation
+ * Copyright (c) 2024-2025 The FreeBSD Foundation
*
* This software was developed by Björn Zeeb under sponsorship from
* the FreeBSD Foundation.
@@ -43,4 +43,51 @@
guard_ ## _n ## _t guard_ ## _n ## _ ## __COUNTER__ \
__cleanup(guard_ ## _n ## _destroy) = guard_ ## _n ## _create
+#define DEFINE_FREE(_n, _t, _f) \
+ static inline void \
+ __free_ ## _n(void *p) \
+ { \
+ _t _T; \
+ \
+ _T = *(_t *)p; \
+ _f; \
+ }
+
+#define __free(_n) __cleanup(__free_##_n)
+
+/*
+ * Given this is a _0 version it should likely be broken up into parts.
+ * But we have no idead what a _1, _2, ... version would do different
+ * until we see a call.
+ * This is used for a not-real-type (rcu). We use a bool to "simulate"
+ * the lock held. Also _T still special, may not always be used, so tag
+ * with __unused (or better the LinuxKPI __maybe_unused).
+ */
+#define DEFINE_LOCK_GUARD_0(_n, _lock, _unlock, ...) \
+ \
+ typedef struct { \
+ bool lock; \
+ __VA_ARGS__; \
+ } guard_ ## _n ## _t; \
+ \
+ static inline void \
+ guard_ ## _n ## _destroy(guard_ ## _n ## _t *_T) \
+ { \
+ if (_T->lock) { \
+ _unlock; \
+ } \
+ } \
+ \
+ static inline guard_ ## _n ## _t \
+ guard_ ## _n ## _create(void) \
+ { \
+ guard_ ## _n ## _t _tmp; \
+ guard_ ## _n ## _t *_T __maybe_unused; \
+ \
+ _tmp.lock = true; \
+ _T = &_tmp; \
+ _lock; \
+ return (_tmp); \
+ }
+
#endif /* _LINUXKPI_LINUX_CLEANUP_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/compiler.h b/sys/compat/linuxkpi/common/include/linux/compiler.h
index fb5ad3bf4fe4..948396144ad6 100644
--- a/sys/compat/linuxkpi/common/include/linux/compiler.h
+++ b/sys/compat/linuxkpi/common/include/linux/compiler.h
@@ -130,4 +130,10 @@
#define is_signed_type(t) ((t)-1 < (t)1)
#define is_unsigned_type(t) ((t)-1 > (t)1)
+#if __has_builtin(__builtin_dynamic_object_size)
+#define __struct_size(_s) __builtin_dynamic_object_size(_s, 0)
+#else
+#define __struct_size(_s) __builtin_object_size(_s, 0)
+#endif
+
#endif /* _LINUXKPI_LINUX_COMPILER_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/device.h b/sys/compat/linuxkpi/common/include/linux/device.h
index 2556b0c45e49..7dd6340746d2 100644
--- a/sys/compat/linuxkpi/common/include/linux/device.h
+++ b/sys/compat/linuxkpi/common/include/linux/device.h
@@ -4,7 +4,7 @@
* Copyright (c) 2010 Panasas, Inc.
* Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
* All rights reserved.
- * Copyright (c) 2021-2022 The FreeBSD Foundation
+ * Copyright (c) 2021-2025 The FreeBSD Foundation
*
* Portions of this software were developed by Björn Zeeb
* under sponsorship from the FreeBSD Foundation.
@@ -284,7 +284,8 @@ int lkpi_devres_destroy(struct device *, void(*release)(struct device *, void *)
void lkpi_devres_release_free_list(struct device *);
void lkpi_devres_unlink(struct device *, void *);
void lkpi_devm_kmalloc_release(struct device *, void *);
-#define devm_kfree(_d, _p) lkpi_devm_kmalloc_release(_d, _p)
+void lkpi_devm_kfree(struct device *, const void *);
+#define devm_kfree(_d, _p) lkpi_devm_kfree(_d, _p)
static inline const char *
dev_driver_string(const struct device *dev)
diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h
index 33850359869f..17041bb03ce8 100644
--- a/sys/compat/linuxkpi/common/include/linux/ieee80211.h
+++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h
@@ -408,6 +408,14 @@ enum ieee80211_sta_state {
IEEE80211_STA_AUTHORIZED = 4, /* 802.1x */
};
+enum ieee80211_sta_rx_bandwidth {
+ IEEE80211_STA_RX_BW_20 = 0,
+ IEEE80211_STA_RX_BW_40,
+ IEEE80211_STA_RX_BW_80,
+ IEEE80211_STA_RX_BW_160,
+ IEEE80211_STA_RX_BW_320,
+};
+
enum ieee80211_tx_info_flags {
/* XXX TODO .. right shift numbers - not sure where that came from? */
IEEE80211_TX_CTL_AMPDU = BIT(0),
diff --git a/sys/compat/linuxkpi/common/include/linux/math.h b/sys/compat/linuxkpi/common/include/linux/math.h
index 5a348a57747b..1d50e011f66d 100644
--- a/sys/compat/linuxkpi/common/include/linux/math.h
+++ b/sys/compat/linuxkpi/common/include/linux/math.h
@@ -56,7 +56,7 @@
__ret; \
})
-#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60600
+#if !defined(LINUXKPI_VERSION) || (LINUXKPI_VERSION >= 60600)
#define abs_diff(x, y) ({ \
__typeof(x) _x = (x); \
__typeof(y) _y = (y); \
diff --git a/sys/compat/linuxkpi/common/include/linux/math64.h b/sys/compat/linuxkpi/common/include/linux/math64.h
index a216d350570f..25ca9da1b622 100644
--- a/sys/compat/linuxkpi/common/include/linux/math64.h
+++ b/sys/compat/linuxkpi/common/include/linux/math64.h
@@ -98,6 +98,12 @@ div64_u64_round_up(uint64_t dividend, uint64_t divisor)
return ((dividend + divisor - 1) / divisor);
}
+static inline uint64_t
+roundup_u64(uint64_t x1, uint32_t x2)
+{
+ return (div_u64(x1 + x2 - 1, x2) * x2);
+}
+
#define DIV64_U64_ROUND_UP(...) \
div64_u64_round_up(__VA_ARGS__)
diff --git a/sys/compat/linuxkpi/common/include/linux/overflow.h b/sys/compat/linuxkpi/common/include/linux/overflow.h
index 9ba9b9500f11..e811037b8ecc 100644
--- a/sys/compat/linuxkpi/common/include/linux/overflow.h
+++ b/sys/compat/linuxkpi/common/include/linux/overflow.h
@@ -33,8 +33,10 @@
* credit to Christian Biere.
*/
#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
-#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
-#define type_min(T) ((T)((T)-type_max(T)-(T)1))
+#define __type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
+#define type_max(t) __type_max(typeof(t))
+#define __type_min(T) ((T)((T)-type_max(T)-(T)1))
+#define type_min(t) __type_min(typeof(t))
/*
* Avoids triggering -Wtype-limits compilation warning,
@@ -59,46 +61,123 @@ static inline bool __must_check __must_check_overflow(bool overflow)
* @b: second addend
* @d: pointer to store sum
*
- * Returns 0 on success.
+ * Returns true on wrap-around, false otherwise.
*
- * *@d holds the results of the attempted addition, but is not considered
- * "safe for use" on a non-zero return value, which indicates that the
- * sum has overflowed or been truncated.
+ * *@d holds the results of the attempted addition, regardless of whether
+ * wrap-around occurred.
*/
#define check_add_overflow(a, b, d) \
__must_check_overflow(__builtin_add_overflow(a, b, d))
/**
+ * wrapping_add() - Intentionally perform a wrapping addition
+ * @type: type for result of calculation
+ * @a: first addend
+ * @b: second addend
+ *
+ * Return the potentially wrapped-around addition without
+ * tripping any wrap-around sanitizers that may be enabled.
+ */
+#define wrapping_add(type, a, b) \
+ ({ \
+ type __val; \
+ __builtin_add_overflow(a, b, &__val); \
+ __val; \
+ })
+
+/**
+ * wrapping_assign_add() - Intentionally perform a wrapping increment assignment
+ * @var: variable to be incremented
+ * @offset: amount to add
+ *
+ * Increments @var by @offset with wrap-around. Returns the resulting
+ * value of @var. Will not trip any wrap-around sanitizers.
+ *
+ * Returns the new value of @var.
+ */
+#define wrapping_assign_add(var, offset) \
+ ({ \
+ typeof(var) *__ptr = &(var); \
+ *__ptr = wrapping_add(typeof(var), *__ptr, offset); \
+ })
+
+/**
* check_sub_overflow() - Calculate subtraction with overflow checking
* @a: minuend; value to subtract from
* @b: subtrahend; value to subtract from @a
* @d: pointer to store difference
*
- * Returns 0 on success.
+ * Returns true on wrap-around, false otherwise.
*
- * *@d holds the results of the attempted subtraction, but is not considered
- * "safe for use" on a non-zero return value, which indicates that the
- * difference has underflowed or been truncated.
+ * *@d holds the results of the attempted subtraction, regardless of whether
+ * wrap-around occurred.
*/
#define check_sub_overflow(a, b, d) \
__must_check_overflow(__builtin_sub_overflow(a, b, d))
/**
+ * wrapping_sub() - Intentionally perform a wrapping subtraction
+ * @type: type for result of calculation
+ * @a: minuend; value to subtract from
+ * @b: subtrahend; value to subtract from @a
+ *
+ * Return the potentially wrapped-around subtraction without
+ * tripping any wrap-around sanitizers that may be enabled.
+ */
+#define wrapping_sub(type, a, b) \
+ ({ \
+ type __val; \
+ __builtin_sub_overflow(a, b, &__val); \
+ __val; \
+ })
+
+/**
+ * wrapping_assign_sub() - Intentionally perform a wrapping decrement assign
+ * @var: variable to be decremented
+ * @offset: amount to subtract
+ *
+ * Decrements @var by @offset with wrap-around. Returns the resulting
+ * value of @var. Will not trip any wrap-around sanitizers.
+ *
+ * Returns the new value of @var.
+ */
+#define wrapping_assign_sub(var, offset) \
+ ({ \
+ typeof(var) *__ptr = &(var); \
+ *__ptr = wrapping_sub(typeof(var), *__ptr, offset); \
+ })
+
+/**
* check_mul_overflow() - Calculate multiplication with overflow checking
* @a: first factor
* @b: second factor
* @d: pointer to store product
*
- * Returns 0 on success.
+ * Returns true on wrap-around, false otherwise.
*
- * *@d holds the results of the attempted multiplication, but is not
- * considered "safe for use" on a non-zero return value, which indicates
- * that the product has overflowed or been truncated.
+ * *@d holds the results of the attempted multiplication, regardless of whether
+ * wrap-around occurred.
*/
#define check_mul_overflow(a, b, d) \
__must_check_overflow(__builtin_mul_overflow(a, b, d))
/**
+ * wrapping_mul() - Intentionally perform a wrapping multiplication
+ * @type: type for result of calculation
+ * @a: first factor
+ * @b: second factor
+ *
+ * Return the potentially wrapped-around multiplication without
+ * tripping any wrap-around sanitizers that may be enabled.
+ */
+#define wrapping_mul(type, a, b) \
+ ({ \
+ type __val; \
+ __builtin_mul_overflow(a, b, &__val); \
+ __val; \
+ })
+
+/**
* check_shl_overflow() - Calculate a left-shifted value and check overflow
* @a: Value to be shifted
* @s: How many bits left to shift
@@ -122,7 +201,7 @@ static inline bool __must_check __must_check_overflow(bool overflow)
typeof(a) _a = a; \
typeof(s) _s = s; \
typeof(d) _d = d; \
- u64 _a_full = _a; \
+ unsigned long long _a_full = _a; \
unsigned int _to_shift = \
is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \
*_d = (_a_full << _to_shift); \
@@ -132,10 +211,10 @@ static inline bool __must_check __must_check_overflow(bool overflow)
#define __overflows_type_constexpr(x, T) ( \
is_unsigned_type(typeof(x)) ? \
- (x) > type_max(typeof(T)) : \
+ (x) > type_max(T) : \
is_unsigned_type(typeof(T)) ? \
- (x) < 0 || (x) > type_max(typeof(T)) : \
- (x) < type_min(typeof(T)) || (x) > type_max(typeof(T)))
+ (x) < 0 || (x) > type_max(T) : \
+ (x) < type_min(T) || (x) > type_max(T))
#define __overflows_type(x, T) ({ \
typeof(T) v = 0; \
@@ -312,27 +391,40 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
struct_size((type *)NULL, member, count)
/**
- * _DEFINE_FLEX() - helper macro for DEFINE_FLEX() family.
- * Enables caller macro to pass (different) initializer.
+ * __DEFINE_FLEX() - helper macro for DEFINE_FLEX() family.
+ * Enables caller macro to pass arbitrary trailing expressions
*
* @type: structure type name, including "struct" keyword.
* @name: Name for a variable to define.
* @member: Name of the array member.
* @count: Number of elements in the array; must be compile-time const.
- * @initializer: initializer expression (could be empty for no init).
+ * @trailer: Trailing expressions for attributes and/or initializers.
*/
-#define _DEFINE_FLEX(type, name, member, count, initializer) \
+#define __DEFINE_FLEX(type, name, member, count, trailer...) \
_Static_assert(__builtin_constant_p(count), \
"onstack flex array members require compile-time const count"); \
union { \
u8 bytes[struct_size_t(type, member, count)]; \
type obj; \
- } name##_u initializer; \
+ } name##_u trailer; \
type *name = (type *)&name##_u
/**
- * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
- * flexible array member.
+ * _DEFINE_FLEX() - helper macro for DEFINE_FLEX() family.
+ * Enables caller macro to pass (different) initializer.
+ *
+ * @type: structure type name, including "struct" keyword.
+ * @name: Name for a variable to define.
+ * @member: Name of the array member.
+ * @count: Number of elements in the array; must be compile-time const.
+ * @initializer: Initializer expression (e.g., pass `= { }` at minimum).
+ */
+#define _DEFINE_FLEX(type, name, member, count, initializer...) \
+ __DEFINE_FLEX(type, name, member, count, = { .obj initializer })
+
+/**
+ * DEFINE_RAW_FLEX() - Define an on-stack instance of structure with a trailing
+ * flexible array member, when it does not have a __counted_by annotation.
*
* @type: structure type name, including "struct" keyword.
* @name: Name for a variable to define.
@@ -342,8 +434,42 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
* Define a zeroed, on-stack, instance of @type structure with a trailing
* flexible array member.
* Use __struct_size(@name) to get compile-time size of it afterwards.
+ * Use __member_size(@name->member) to get compile-time size of @name members.
+ * Use STACK_FLEX_ARRAY_SIZE(@name, @member) to get compile-time number of
+ * elements in array @member.
+ */
+#define DEFINE_RAW_FLEX(type, name, member, count) \
+ __DEFINE_FLEX(type, name, member, count, = { })
+
+/**
+ * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
+ * flexible array member.
+ *
+ * @TYPE: structure type name, including "struct" keyword.
+ * @NAME: Name for a variable to define.
+ * @MEMBER: Name of the array member.
+ * @COUNTER: Name of the __counted_by member.
+ * @COUNT: Number of elements in the array; must be compile-time const.
+ *
+ * Define a zeroed, on-stack, instance of @TYPE structure with a trailing
+ * flexible array member.
+ * Use __struct_size(@NAME) to get compile-time size of it afterwards.
+ * Use __member_size(@NAME->member) to get compile-time size of @NAME members.
+ * Use STACK_FLEX_ARRAY_SIZE(@name, @member) to get compile-time number of
+ * elements in array @member.
+ */
+#define DEFINE_FLEX(TYPE, NAME, MEMBER, COUNTER, COUNT) \
+ _DEFINE_FLEX(TYPE, NAME, MEMBER, COUNT, = { .COUNTER = COUNT, })
+
+/**
+ * STACK_FLEX_ARRAY_SIZE() - helper macro for DEFINE_FLEX() family.
+ * Returns the number of elements in @array.
+ *
+ * @name: Name for a variable defined in DEFINE_RAW_FLEX()/DEFINE_FLEX().
+ * @array: Name of the array member.
*/
-#define DEFINE_FLEX(type, name, member, count) \
- _DEFINE_FLEX(type, name, member, count, = {})
+#define STACK_FLEX_ARRAY_SIZE(name, array) \
+ (__member_size((name)->array) / sizeof(*(name)->array) + \
+ __must_be_array((name)->array))
#endif /* _LINUXKPI_LINUX_OVERFLOW_H */
diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h
index 3fd4191b9917..d891d0df3546 100644
--- a/sys/compat/linuxkpi/common/include/linux/pci.h
+++ b/sys/compat/linuxkpi/common/include/linux/pci.h
@@ -355,7 +355,6 @@ struct pci_dev {
TAILQ_HEAD(, pci_mmio_region) mmio;
};
-int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name);
int pci_alloc_irq_vectors(struct pci_dev *pdev, int minv, int maxv,
unsigned int flags);
bool pci_device_is_present(struct pci_dev *pdev);
@@ -365,10 +364,13 @@ void __iomem **linuxkpi_pcim_iomap_table(struct pci_dev *pdev);
void *linuxkpi_pci_iomap_range(struct pci_dev *, int,
unsigned long, unsigned long);
void *linuxkpi_pci_iomap(struct pci_dev *, int, unsigned long);
+void *linuxkpi_pcim_iomap(struct pci_dev *, int, unsigned long);
void linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res);
int linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask,
const char *name);
+int linuxkpi_pci_request_region(struct pci_dev *, int, const char *);
int linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name);
+int linuxkpi_pcim_request_all_regions(struct pci_dev *, const char *);
void linuxkpi_pci_release_region(struct pci_dev *pdev, int bar);
void linuxkpi_pci_release_regions(struct pci_dev *pdev);
int linuxkpi_pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries,
@@ -561,12 +563,16 @@ done:
return (pdev->bus->self);
}
+#define pci_request_region(pdev, bar, res_name) \
+ linuxkpi_pci_request_region(pdev, bar, res_name)
#define pci_release_region(pdev, bar) \
linuxkpi_pci_release_region(pdev, bar)
-#define pci_release_regions(pdev) \
- linuxkpi_pci_release_regions(pdev)
#define pci_request_regions(pdev, res_name) \
linuxkpi_pci_request_regions(pdev, res_name)
+#define pci_release_regions(pdev) \
+ linuxkpi_pci_release_regions(pdev)
+#define pcim_request_all_regions(pdev, name) \
+ linuxkpi_pcim_request_all_regions(pdev, name)
static inline void
lkpi_pci_disable_msix(struct pci_dev *pdev)
@@ -803,6 +809,8 @@ static inline void pci_disable_sriov(struct pci_dev *dev)
linuxkpi_pci_iomap_range(pdev, mmio_bar, mmio_off, mmio_size)
#define pci_iomap(pdev, mmio_bar, mmio_size) \
linuxkpi_pci_iomap(pdev, mmio_bar, mmio_size)
+#define pcim_iomap(pdev, bar, maxlen) \
+ linuxkpi_pcim_iomap(pdev, bar, maxlen)
#define pci_iounmap(pdev, res) \
linuxkpi_pci_iounmap(pdev, res)
@@ -1445,6 +1453,9 @@ linuxkpi_pci_get_device(uint32_t vendor, uint32_t device, struct pci_dev *odev)
return (lkpi_pci_get_device(vendor, device, odev));
}
+#define for_each_pci_dev(_pdev) \
+ while ((_pdev = linuxkpi_pci_get_device(PCI_ANY_ID, PCI_ANY_ID, _pdev)) != NULL)
+
/* This is a FreeBSD extension so we can use bus_*(). */
static inline void
linuxkpi_pcim_want_to_use_bus_functions(struct pci_dev *pdev)
diff --git a/sys/compat/linuxkpi/common/include/linux/rcupdate.h b/sys/compat/linuxkpi/common/include/linux/rcupdate.h
index 85d766c8dbc9..4aceb7296cd6 100644
--- a/sys/compat/linuxkpi/common/include/linux/rcupdate.h
+++ b/sys/compat/linuxkpi/common/include/linux/rcupdate.h
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2016-2017 Mellanox Technologies, Ltd.
* All rights reserved.
- * Copyright (c) 2024 The FreeBSD Foundation
+ * Copyright (c) 2024-2025 The FreeBSD Foundation
*
* Portions of this software were developed by Björn Zeeb
* under sponsorship from the FreeBSD Foundation.
@@ -35,6 +35,7 @@
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/kernel.h>
+#include <linux/cleanup.h>
#include <machine/atomic.h>
@@ -162,4 +163,6 @@ void linux_synchronize_rcu(unsigned type);
#define init_rcu_head_on_stack(...)
#define destroy_rcu_head_on_stack(...)
+DEFINE_LOCK_GUARD_0(rcu, rcu_read_lock(), rcu_read_unlock())
+
#endif /* _LINUXKPI_LINUX_RCUPDATE_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/skbuff.h b/sys/compat/linuxkpi/common/include/linux/skbuff.h
index 0f192ceab318..6e41c368a8b8 100644
--- a/sys/compat/linuxkpi/common/include/linux/skbuff.h
+++ b/sys/compat/linuxkpi/common/include/linux/skbuff.h
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2020-2025 The FreeBSD Foundation
- * Copyright (c) 2021-2023 Bjoern A. Zeeb
+ * Copyright (c) 2021-2025 Bjoern A. Zeeb
*
* This software was developed by Björn Zeeb under sponsorship from
* the FreeBSD Foundation.
@@ -47,13 +47,11 @@
#include <linux/ktime.h>
#include <linux/compiler.h>
-#include "opt_wlan.h"
-
-/* Currently this is only used for wlan so we can depend on that. */
-#if defined(IEEE80211_DEBUG) && !defined(SKB_DEBUG)
-#define SKB_DEBUG
-#endif
-
+/*
+ * At least the net/intel-irdma-kmod port pulls this header in; likely through
+ * if_ether.h (see PR289268). This means we no longer can rely on
+ * IEEE80211_DEBUG (opt_wlan.h) to automatically set SKB_DEBUG.
+ */
/* #define SKB_DEBUG */
#ifdef SKB_DEBUG
diff --git a/sys/compat/linuxkpi/common/include/linux/slab.h b/sys/compat/linuxkpi/common/include/linux/slab.h
index 47e3d133eb6c..0e649e1e3c4a 100644
--- a/sys/compat/linuxkpi/common/include/linux/slab.h
+++ b/sys/compat/linuxkpi/common/include/linux/slab.h
@@ -40,8 +40,10 @@
#include <linux/compat.h>
#include <linux/types.h>
#include <linux/gfp.h>
+#include <linux/err.h>
#include <linux/llist.h>
#include <linux/overflow.h>
+#include <linux/cleanup.h>
MALLOC_DECLARE(M_KMALLOC);
@@ -153,6 +155,8 @@ kfree(const void *ptr)
lkpi_kfree(ptr);
}
+DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T))
+
/*
* Other k*alloc() funtions using the above as underlying allocator.
*/
diff --git a/sys/compat/linuxkpi/common/include/linux/string_choices.h b/sys/compat/linuxkpi/common/include/linux/string_choices.h
new file mode 100644
index 000000000000..74aa3fd019b2
--- /dev/null
+++ b/sys/compat/linuxkpi/common/include/linux/string_choices.h
@@ -0,0 +1,71 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LINUXKPI_LINUX_STRING_CHOICES_H_
+#define _LINUXKPI_LINUX_STRING_CHOICES_H_
+
+#include <sys/types.h>
+
+static inline const char *
+str_yes_no(bool value)
+{
+ if (value)
+ return "yes";
+ else
+ return "no";
+}
+
+static inline const char *
+str_on_off(bool value)
+{
+ if (value)
+ return "on";
+ else
+ return "off";
+}
+
+static inline const char *
+str_enabled_disabled(bool value)
+{
+ if (value)
+ return "enabled";
+ else
+ return "disabled";
+}
+
+static inline const char *
+str_enable_disable(bool value)
+{
+ if (value)
+ return "enable";
+ else
+ return "disable";
+}
+
+#define str_disable_enable(_v) str_enable_disable(!(_v))
+
+#endif
diff --git a/sys/compat/linuxkpi/common/include/linux/string_helpers.h b/sys/compat/linuxkpi/common/include/linux/string_helpers.h
index 2c6fe0b1708d..07d113c0cb21 100644
--- a/sys/compat/linuxkpi/common/include/linux/string_helpers.h
+++ b/sys/compat/linuxkpi/common/include/linux/string_helpers.h
@@ -1,71 +1,12 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2023 Jean-Sébastien Pédron <dumbbell@FreeBSD.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice unmodified, this list of conditions, and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+/*
+ * Copyright (c) 2025 The FreeBSD Foundation
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef _LINUXKPI_LINUX_STRING_HELPERS_H_
#define _LINUXKPI_LINUX_STRING_HELPERS_H_
-#include <sys/types.h>
-
-static inline const char *
-str_yes_no(bool value)
-{
- if (value)
- return "yes";
- else
- return "no";
-}
-
-static inline const char *
-str_on_off(bool value)
-{
- if (value)
- return "on";
- else
- return "off";
-}
-
-static inline const char *
-str_enabled_disabled(bool value)
-{
- if (value)
- return "enabled";
- else
- return "disabled";
-}
-
-static inline const char *
-str_enable_disable(bool value)
-{
- if (value)
- return "enable";
- else
- return "disable";
-}
-
-#define str_disable_enable(_v) str_enable_disable(!(_v))
+#include <linux/string_choices.h>
#endif
diff --git a/sys/compat/linuxkpi/common/include/linux/timer.h b/sys/compat/linuxkpi/common/include/linux/timer.h
index a635f0faea59..d48939e28a02 100644
--- a/sys/compat/linuxkpi/common/include/linux/timer.h
+++ b/sys/compat/linuxkpi/common/include/linux/timer.h
@@ -49,8 +49,13 @@ extern unsigned long linux_timer_hz_mask;
#define TIMER_IRQSAFE 0x0001
+#if defined(LINUXKPI_VERSION) && (LINUXKPI_VERSION < 61600)
#define from_timer(var, arg, field) \
container_of(arg, typeof(*(var)), field)
+#else
+#define timer_container_of(var, arg, field) \
+ container_of(arg, typeof(*(var)), field)
+#endif
#define timer_setup(timer, func, flags) do { \
CTASSERT(((flags) & ~TIMER_IRQSAFE) == 0); \
@@ -79,11 +84,23 @@ extern unsigned long linux_timer_hz_mask;
extern int mod_timer(struct timer_list *, unsigned long);
extern void add_timer(struct timer_list *);
extern void add_timer_on(struct timer_list *, int cpu);
-extern int del_timer(struct timer_list *);
-extern int del_timer_sync(struct timer_list *);
+
+extern int timer_delete(struct timer_list *);
extern int timer_delete_sync(struct timer_list *);
extern int timer_shutdown_sync(struct timer_list *);
+static inline int
+del_timer(struct timer_list *tl)
+{
+ return (timer_delete(tl));
+}
+
+static inline int
+del_timer_sync(struct timer_list *tl)
+{
+ return (timer_delete_sync(tl));
+}
+
#define timer_pending(timer) callout_pending(&(timer)->callout)
#define round_jiffies(j) \
((unsigned long)(((j) + linux_timer_hz_mask) & ~linux_timer_hz_mask))
diff --git a/sys/compat/linuxkpi/common/include/net/mac80211.h b/sys/compat/linuxkpi/common/include/net/mac80211.h
index 0106e6648bd4..8de03410c6b6 100644
--- a/sys/compat/linuxkpi/common/include/net/mac80211.h
+++ b/sys/compat/linuxkpi/common/include/net/mac80211.h
@@ -737,7 +737,7 @@ struct ieee80211_link_sta {
struct ieee80211_he_6ghz_capa he_6ghz_capa;
struct ieee80211_sta_eht_cap eht_cap;
uint8_t rx_nss;
- enum ieee80211_sta_rx_bw bandwidth;
+ enum ieee80211_sta_rx_bandwidth bandwidth;
enum ieee80211_smps_mode smps_mode;
struct ieee80211_sta_agg agg;
struct ieee80211_sta_txpwr txpwr;
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 3f850653bc7c..bc4b334de28e 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -401,7 +401,7 @@ lkpi_80211_dump_stas(SYSCTL_HANDLER_ARGS)
return (0);
}
-static enum ieee80211_sta_rx_bw
+static enum ieee80211_sta_rx_bandwidth
lkpi_cw_to_rx_bw(enum nl80211_chan_width cw)
{
switch (cw) {
@@ -425,7 +425,7 @@ lkpi_cw_to_rx_bw(enum nl80211_chan_width cw)
}
static enum nl80211_chan_width
-lkpi_rx_bw_to_cw(enum ieee80211_sta_rx_bw rx_bw)
+lkpi_rx_bw_to_cw(enum ieee80211_sta_rx_bandwidth rx_bw)
{
switch (rx_bw) {
case IEEE80211_STA_RX_BW_20:
@@ -446,7 +446,7 @@ lkpi_sync_chanctx_cw_from_rx_bw(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_sta *sta)
{
struct ieee80211_chanctx_conf *chanctx_conf;
- enum ieee80211_sta_rx_bw old_bw;
+ enum ieee80211_sta_rx_bandwidth old_bw;
uint32_t changed;
chanctx_conf = rcu_dereference_protected(vif->bss_conf.chanctx_conf,
@@ -551,7 +551,7 @@ static void
lkpi_sta_sync_vht_from_ni(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_node *ni)
{
- enum ieee80211_sta_rx_bw bw;
+ enum ieee80211_sta_rx_bandwidth bw;
uint32_t width;
int rx_nss;
uint16_t rx_mcs_map;
@@ -1890,7 +1890,25 @@ lkpi_update_dtim_tsf(struct ieee80211_vif *vif, struct ieee80211_node *ni,
vif->bss_conf.beacon_int = 16;
bss_changed |= BSS_CHANGED_BEACON_INT;
}
- if (vif->bss_conf.dtim_period != ni->ni_dtim_period &&
+
+ /*
+ * lkpi_iv_sta_recv_mgmt() will directly call into this function.
+ * iwlwifi(4) in iwl_mvm_bss_info_changed_station_common() will
+ * stop seesion protection the moment it sees
+ * BSS_CHANGED_BEACON_INFO (with the expectations that it was
+ * "a beacon from the associated AP"). It will also update
+ * the beacon filter in that case. This is the only place
+ * we set the BSS_CHANGED_BEACON_INFO on the non-teardown
+ * path so make sure we only do run this check once we are
+ * assoc. (*iv_recv_mgmt)() will be called before we enter
+ * here so the ni will be updates with information from the
+ * beacon via net80211::sta_recv_mgmt(). We also need to
+ * make sure we do not do it on every beacon we still may
+ * get so only do if something changed. vif->bss_conf.dtim_period
+ * should be 0 as we start up (we also reset it on teardown).
+ */
+ if (vif->cfg.assoc &&
+ vif->bss_conf.dtim_period != ni->ni_dtim_period &&
ni->ni_dtim_period > 0) {
vif->bss_conf.dtim_period = ni->ni_dtim_period;
bss_changed |= BSS_CHANGED_BEACON_INFO;
@@ -2550,12 +2568,6 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int
lvif->lvif_bss_synched = false;
LKPI_80211_LVIF_UNLOCK(lvif);
lkpi_lsta_remove(lsta, lvif);
- /*
- * The very last release the reference on the ni for the ni/lsta on
- * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
- * and potentially freed.
- */
- ieee80211_free_node(ni);
/* conf_tx */
@@ -2564,6 +2576,18 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int
out:
wiphy_unlock(hw->wiphy);
IEEE80211_LOCK(vap->iv_ic);
+ if (error == 0) {
+ /*
+ * We do this outside the wiphy lock as net80211::node_free() may call
+ * into crypto code to delete keys and we have a recursed on
+ * non-recursive sx panic. Also only do this if we get here w/o error.
+ *
+ * The very last release the reference on the ni for the ni/lsta on
+ * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
+ * and potentially freed.
+ */
+ ieee80211_free_node(ni);
+ }
return (error);
}
@@ -2888,12 +2912,6 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i
lvif->lvif_bss_synched = false;
LKPI_80211_LVIF_UNLOCK(lvif);
lkpi_lsta_remove(lsta, lvif);
- /*
- * The very last release the reference on the ni for the ni/lsta on
- * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
- * and potentially freed.
- */
- ieee80211_free_node(ni);
/* conf_tx */
@@ -2903,6 +2921,18 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i
out:
wiphy_unlock(hw->wiphy);
IEEE80211_LOCK(vap->iv_ic);
+ if (error == EALREADY) {
+ /*
+ * We do this outside the wiphy lock as net80211::node_free() may call
+ * into crypto code to delete keys and we have a recursed on
+ * non-recursive sx panic. Also only do this if we get here w/o error.
+ *
+ * The very last release the reference on the ni for the ni/lsta on
+ * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
+ * and potentially freed.
+ */
+ ieee80211_free_node(ni);
+ }
outni:
return (error);
}
@@ -3504,12 +3534,6 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
lvif->lvif_bss = NULL;
lvif->lvif_bss_synched = false;
LKPI_80211_LVIF_UNLOCK(lvif);
- /*
- * The very last release the reference on the ni for the ni/lsta on
- * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
- * and potentially freed.
- */
- ieee80211_free_node(ni);
/* conf_tx */
@@ -3519,6 +3543,18 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int
out:
wiphy_unlock(hw->wiphy);
IEEE80211_LOCK(vap->iv_ic);
+ if (error == EALREADY) {
+ /*
+ * We do this outside the wiphy lock as net80211::node_free() may call
+ * into crypto code to delete keys and we have a recursed on
+ * non-recursive sx panic. Also only do this if we get here w/o error.
+ *
+ * The very last release the reference on the ni for the ni/lsta on
+ * lvif->lvif_bss. Upon return from this both ni and lsta are invalid
+ * and potentially freed.
+ */
+ ieee80211_free_node(ni);
+ }
outni:
return (error);
}
@@ -3810,6 +3846,7 @@ lkpi_iv_sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
enum ieee80211_bss_changed bss_changed;
lvif = VAP_TO_LVIF(ni->ni_vap);
+ vif = LVIF_TO_VIF(lvif);
lvif->iv_recv_mgmt(ni, m0, subtype, rxs, rssi, nf);
@@ -3817,13 +3854,18 @@ lkpi_iv_sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
break;
case IEEE80211_FC0_SUBTYPE_BEACON:
- lvif->beacons++;
+ /*
+ * Only count beacons when assoc. SCAN has its own logging.
+ * This is for connection/beacon loss/session protection almost
+ * over debugging when trying to get into a stable RUN state.
+ */
+ if (vif->cfg.assoc)
+ lvif->beacons++;
break;
default:
return;
}
- vif = LVIF_TO_VIF(lvif);
lhw = ni->ni_ic->ic_softc;
hw = LHW_TO_HW(lhw);
@@ -4059,13 +4101,9 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
* Modern chipset/fw/drv will do A-MPDU in drv/fw and fail
* to do so if they cannot do the crypto too.
*/
- if (!lkpi_hwcrypto && ieee80211_hw_check(hw, AMPDU_AGGREGATION))
+ if (!lkpi_hwcrypto && IEEE80211_CONF_AMPDU_OFFLOAD(ic))
vap->iv_flags_ht &= ~IEEE80211_FHT_AMPDU_RX;
#endif
-#if defined(LKPI_80211_HT)
- /* 20250125-BZ Keep A-MPDU TX cleared until we sorted out AddBA for all drivers. */
- vap->iv_flags_ht &= ~IEEE80211_FHT_AMPDU_TX;
-#endif
if (hw->max_listen_interval == 0)
hw->max_listen_interval = 7 * (ic->ic_lintval / ic->ic_bintval);
@@ -6609,6 +6647,14 @@ linuxkpi_ieee80211_ifattach(struct ieee80211_hw *hw)
if (ieee80211_hw_check(hw, SUPPORTS_TX_FRAG))
ic->ic_flags_ext |= IEEE80211_FEXT_FRAG_OFFLOAD;
+ /* Does HW support full AMPDU[-TX] offload? */
+ if (ieee80211_hw_check(hw, AMPDU_AGGREGATION))
+ ic->ic_flags_ext |= IEEE80211_FEXT_AMPDU_OFFLOAD;
+#ifdef __notyet__
+ if (ieee80211_hw_check(hw, TX_AMSDU))
+ if (ieee80211_hw_check(hw, SUPPORTS_AMSDU_IN_AMPDU))
+#endif
+
/*
* The wiphy variables report bitmasks of avail antennas.
* (*get_antenna) get the current bitmask sets which can be
@@ -7786,7 +7832,7 @@ lkpi_wiphy_delayed_work_timer(struct timer_list *tl)
{
struct wiphy_delayed_work *wdwk;
- wdwk = from_timer(wdwk, tl, timer);
+ wdwk = timer_container_of(wdwk, tl, timer);
wiphy_work_queue(wdwk->wiphy, &wdwk->work);
}
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index dcdec0dfcc78..458744a9fec6 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -2120,7 +2120,7 @@ add_timer_on(struct timer_list *timer, int cpu)
}
int
-del_timer(struct timer_list *timer)
+timer_delete(struct timer_list *timer)
{
if (callout_stop(&(timer)->callout) == -1)
@@ -2129,7 +2129,7 @@ del_timer(struct timer_list *timer)
}
int
-del_timer_sync(struct timer_list *timer)
+timer_delete_sync(struct timer_list *timer)
{
if (callout_drain(&(timer)->callout) == -1)
@@ -2138,13 +2138,6 @@ del_timer_sync(struct timer_list *timer)
}
int
-timer_delete_sync(struct timer_list *timer)
-{
-
- return (del_timer_sync(timer));
-}
-
-int
timer_shutdown_sync(struct timer_list *timer)
{
diff --git a/sys/compat/linuxkpi/common/src/linux_devres.c b/sys/compat/linuxkpi/common/src/linux_devres.c
index 84f03ba0dd7d..23c91cb5ab2f 100644
--- a/sys/compat/linuxkpi/common/src/linux_devres.c
+++ b/sys/compat/linuxkpi/common/src/linux_devres.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2020-2021 The FreeBSD Foundation
+ * Copyright (c) 2020-2025 The FreeBSD Foundation
*
* This software was developed by Bj\xc3\xb6rn Zeeb under sponsorship from
* the FreeBSD Foundation.
@@ -223,6 +223,30 @@ lkpi_devm_kmalloc_release(struct device *dev __unused, void *p __unused)
/* Nothing to do. Freed with the devres. */
}
+static int
+lkpi_devm_kmalloc_match(struct device *dev __unused, void *p, void *mp)
+{
+ return (p == mp);
+}
+
+void
+lkpi_devm_kfree(struct device *dev, const void *p)
+{
+ void *mp;
+ int error;
+
+ if (p == NULL)
+ return;
+
+ /* I assume Linux simply casts the const away... */
+ mp = __DECONST(void *, p);
+ error = lkpi_devres_destroy(dev, lkpi_devm_kmalloc_release,
+ lkpi_devm_kmalloc_match, mp);
+ if (error != 0)
+ dev_warn(dev, "%s: lkpi_devres_destroy failed with %d\n",
+ __func__, error);
+}
+
struct devres_action {
void *data;
void (*action)(void *);
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index d5bbbea1eb2c..43fd6ad28ac4 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -111,6 +111,9 @@ static device_method_t pci_methods[] = {
DEVMETHOD(pci_iov_uninit, linux_pci_iov_uninit),
DEVMETHOD(pci_iov_add_vf, linux_pci_iov_add_vf),
+ /* Bus interface. */
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+
/* backlight interface */
DEVMETHOD(backlight_update_status, linux_backlight_update_status),
DEVMETHOD(backlight_get_status, linux_backlight_get_status),
@@ -145,6 +148,23 @@ struct linux_dma_priv {
#define DMA_PRIV_LOCK(priv) mtx_lock(&(priv)->lock)
#define DMA_PRIV_UNLOCK(priv) mtx_unlock(&(priv)->lock)
+static void
+lkpi_set_pcim_iomap_devres(struct pcim_iomap_devres *dr, int bar,
+ void *res)
+{
+ dr->mmio_table[bar] = (void *)rman_get_bushandle(res);
+ dr->res_table[bar] = res;
+}
+
+static bool
+lkpi_pci_bar_id_valid(int bar)
+{
+ if (bar < 0 || bar > PCIR_MAX_BAR_0)
+ return (false);
+
+ return (true);
+}
+
static int
linux_pdev_dma_uninit(struct pci_dev *pdev)
{
@@ -289,12 +309,18 @@ lkpi_pci_get_device(uint32_t vendor, uint32_t device, struct pci_dev *odev)
{
struct pci_dev *pdev, *found;
- KASSERT(odev == NULL, ("%s: odev argument not yet supported\n", __func__));
-
found = NULL;
spin_lock(&pci_lock);
list_for_each_entry(pdev, &pci_devices, links) {
- if (pdev->vendor == vendor && pdev->device == device) {
+ /* Walk until we find odev. */
+ if (odev != NULL) {
+ if (pdev == odev)
+ odev = NULL;
+ continue;
+ }
+
+ if ((pdev->vendor == vendor || vendor == PCI_ANY_ID) &&
+ (pdev->device == device || device == PCI_ANY_ID)) {
found = pdev;
break;
}
@@ -757,6 +783,9 @@ _lkpi_pci_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen __unused)
struct pci_mmio_region *mmio, *p;
int type;
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (NULL);
+
type = pci_resource_type(pdev, bar);
if (type < 0) {
device_printf(pdev->dev.bsddev, "%s: bar %d type %d\n",
@@ -797,6 +826,9 @@ linuxkpi_pci_iomap_range(struct pci_dev *pdev, int bar,
{
struct resource *res;
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (NULL);
+
res = _lkpi_pci_iomap(pdev, bar, maxlen);
if (res == NULL)
return (NULL);
@@ -810,9 +842,41 @@ linuxkpi_pci_iomap_range(struct pci_dev *pdev, int bar,
void *
linuxkpi_pci_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
{
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (NULL);
+
return (linuxkpi_pci_iomap_range(pdev, bar, 0, maxlen));
}
+void *
+linuxkpi_pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
+{
+ struct pcim_iomap_devres *dr;
+ void *res;
+
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (NULL);
+
+ dr = lkpi_pcim_iomap_devres_find(pdev);
+ if (dr == NULL)
+ return (NULL);
+
+ if (dr->res_table[bar] != NULL)
+ return (dr->res_table[bar]);
+
+ res = linuxkpi_pci_iomap(pdev, bar, maxlen);
+ if (res == NULL) {
+ /*
+ * Do not free the devres in case there were
+ * other valid mappings before already.
+ */
+ return (NULL);
+ }
+ lkpi_set_pcim_iomap_devres(dr, bar, res);
+
+ return (res);
+}
+
void
linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res)
{
@@ -864,8 +928,7 @@ linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask, const char *nam
res = _lkpi_pci_iomap(pdev, bar, 0);
if (res == NULL)
goto err;
- dr->mmio_table[bar] = (void *)rman_get_bushandle(res);
- dr->res_table[bar] = res;
+ lkpi_set_pcim_iomap_devres(dr, bar, res);
mappings |= (1 << bar);
}
@@ -1099,8 +1162,9 @@ pci_resource_len(struct pci_dev *pdev, int bar)
return (rle->count);
}
-int
-pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
+static int
+lkpi_pci_request_region(struct pci_dev *pdev, int bar, const char *res_name,
+ bool managed)
{
struct resource *res;
struct pci_devres *dr;
@@ -1108,9 +1172,20 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
int rid;
int type;
+ if (!lkpi_pci_bar_id_valid(bar))
+ return (-EINVAL);
+
+ /*
+ * If the bar is not valid, return success without adding the BAR;
+ * otherwise linuxkpi_pcim_request_all_regions() will error.
+ */
+ if (pci_resource_len(pdev, bar) == 0)
+ return (0);
+ /* Likewise if it is neither IO nor MEM, nothing to do for us. */
type = pci_resource_type(pdev, bar);
if (type < 0)
- return (-ENODEV);
+ return (0);
+
rid = PCIR_BAR(bar);
res = bus_alloc_resource_any(pdev->dev.bsddev, type, &rid,
RF_ACTIVE|RF_SHAREABLE);
@@ -1123,11 +1198,16 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
/*
* It seems there is an implicit devres tracking on these if the device
- * is managed; otherwise the resources are not automatiaclly freed on
- * FreeBSD/LinuxKPI tough they should be/are expected to be by Linux
- * drivers.
+ * is managed (lkpi_pci_devres_find() case); otherwise the resources are
+ * not automatically freed on FreeBSD/LinuxKPI though they should be/are
+ * expected to be by Linux drivers.
+ * Otherwise if we are called from a pcim-function with the managed
+ * argument set, we need to track devres independent of pdev->managed.
*/
- dr = lkpi_pci_devres_find(pdev);
+ if (managed)
+ dr = lkpi_pci_devres_get_alloc(pdev);
+ else
+ dr = lkpi_pci_devres_find(pdev);
if (dr != NULL) {
dr->region_mask |= (1 << bar);
dr->region_table[bar] = res;
@@ -1144,6 +1224,12 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
}
int
+linuxkpi_pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
+{
+ return (lkpi_pci_request_region(pdev, bar, res_name, false));
+}
+
+int
linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name)
{
int error;
@@ -1159,6 +1245,24 @@ linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name)
return (0);
}
+int
+linuxkpi_pcim_request_all_regions(struct pci_dev *pdev, const char *res_name)
+{
+ int bar, error;
+
+ for (bar = 0; bar <= PCIR_MAX_BAR_0; bar++) {
+ error = lkpi_pci_request_region(pdev, bar, res_name, true);
+ if (error != 0) {
+ device_printf(pdev->dev.bsddev, "%s: bar %d res_name '%s': "
+ "lkpi_pci_request_region returned %d\n", __func__,
+ bar, res_name, error);
+ pci_release_regions(pdev);
+ return (error);
+ }
+ }
+ return (0);
+}
+
void
linuxkpi_pci_release_region(struct pci_dev *pdev, int bar)
{
diff --git a/sys/compat/linuxkpi/dummy/include/kunit/skbuff.h b/sys/compat/linuxkpi/dummy/include/kunit/skbuff.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/sys/compat/linuxkpi/dummy/include/kunit/skbuff.h
diff --git a/sys/compat/linuxkpi/dummy/include/kunit/test-bug.h b/sys/compat/linuxkpi/dummy/include/kunit/test-bug.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/sys/compat/linuxkpi/dummy/include/kunit/test-bug.h
diff --git a/sys/compat/linuxkpi/dummy/include/kunit/test.h b/sys/compat/linuxkpi/dummy/include/kunit/test.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/sys/compat/linuxkpi/dummy/include/kunit/test.h