diff options
Diffstat (limited to 'sys/compat')
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 |