Merge e774d5f1bc ("Merge tag 'riscv-for-linus-v7.0-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux") into android-mainline
Steps on the way to v7.0 Change-Id: I62479c0e28c7add8b5263c0a1d9cd0e3ca961caa Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
commit
5bdfe143f7
74 files changed
+695
-431
No files matched your search
@@ -76,34 +76,49 @@ the program.
|
||||
4. prctl() enabling
|
||||
--------------------
|
||||
|
||||
:c:macro:`PR_SET_INDIR_BR_LP_STATUS` / :c:macro:`PR_GET_INDIR_BR_LP_STATUS` /
|
||||
:c:macro:`PR_LOCK_INDIR_BR_LP_STATUS` are three prctls added to manage indirect
|
||||
branch tracking. These prctls are architecture-agnostic and return -EINVAL if
|
||||
the underlying functionality is not supported.
|
||||
Per-task indirect branch tracking state can be monitored and
|
||||
controlled via the :c:macro:`PR_GET_CFI` and :c:macro:`PR_SET_CFI`
|
||||
``prctl()` arguments (respectively), by supplying
|
||||
:c:macro:`PR_CFI_BRANCH_LANDING_PADS` as the second argument. These
|
||||
are architecture-agnostic, and will return -EINVAL if the underlying
|
||||
functionality is not supported.
|
||||
|
||||
* prctl(PR_SET_INDIR_BR_LP_STATUS, unsigned long arg)
|
||||
* prctl(:c:macro:`PR_SET_CFI`, :c:macro:`PR_CFI_BRANCH_LANDING_PADS`, unsigned long arg)
|
||||
|
||||
If arg1 is :c:macro:`PR_INDIR_BR_LP_ENABLE` and if CPU supports
|
||||
``zicfilp`` then the kernel will enable indirect branch tracking for the
|
||||
task. The dynamic loader can issue this :c:macro:`prctl` once it has
|
||||
arg is a bitmask.
|
||||
|
||||
If :c:macro:`PR_CFI_ENABLE` is set in arg, and the CPU supports
|
||||
``zicfilp``, then the kernel will enable indirect branch tracking for
|
||||
the task. The dynamic loader can issue this ``prctl()`` once it has
|
||||
determined that all the objects loaded in the address space support
|
||||
indirect branch tracking. Additionally, if there is a `dlopen` to an
|
||||
object which wasn't compiled with ``zicfilp``, the dynamic loader can
|
||||
issue this prctl with arg1 set to 0 (i.e. :c:macro:`PR_INDIR_BR_LP_ENABLE`
|
||||
cleared).
|
||||
indirect branch tracking.
|
||||
|
||||
* prctl(PR_GET_INDIR_BR_LP_STATUS, unsigned long * arg)
|
||||
Indirect branch tracking state can also be locked once enabled. This
|
||||
prevents the task from subsequently disabling it. This is done by
|
||||
setting the bit :c:macro:`PR_CFI_LOCK` in arg. Either indirect branch
|
||||
tracking must already be enabled for the task, or the bit
|
||||
:c:macro:`PR_CFI_ENABLE` must also be set in arg. This is intended
|
||||
for environments that wish to run with a strict security posture that
|
||||
do not wish to load objects without ``zicfilp`` support.
|
||||
|
||||
Returns the current status of indirect branch tracking. If enabled
|
||||
it'll return :c:macro:`PR_INDIR_BR_LP_ENABLE`
|
||||
Indirect branch tracking can also be disabled for the task, assuming
|
||||
that it has not previously been enabled and locked. If there is a
|
||||
``dlopen()`` to an object which wasn't compiled with ``zicfilp``, the
|
||||
dynamic loader can issue this ``prctl()`` with arg set to
|
||||
:c:macro:`PR_CFI_DISABLE`. Disabling indirect branch tracking for the
|
||||
task is not possible if it has previously been enabled and locked.
|
||||
|
||||
* prctl(PR_LOCK_INDIR_BR_LP_STATUS, unsigned long arg)
|
||||
|
||||
Locks the current status of indirect branch tracking on the task. User
|
||||
space may want to run with a strict security posture and wouldn't want
|
||||
loading of objects without ``zicfilp`` support in them, to disallow
|
||||
disabling of indirect branch tracking. In this case, user space can
|
||||
use this prctl to lock the current settings.
|
||||
* prctl(:c:macro:`PR_GET_CFI`, :c:macro:`PR_CFI_BRANCH_LANDING_PADS`, unsigned long * arg)
|
||||
|
||||
Returns the current status of indirect branch tracking into a bitmask
|
||||
stored into the memory location pointed to by arg. The bitmask will
|
||||
have the :c:macro:`PR_CFI_ENABLE` bit set if indirect branch tracking
|
||||
is currently enabled for the task, and if it is locked, will
|
||||
additionally have the :c:macro:`PR_CFI_LOCK` bit set. If indirect
|
||||
branch tracking is currently disabled for the task, the
|
||||
:c:macro:`PR_CFI_DISABLE` bit will be set.
|
||||
|
||||
|
||||
5. violations related to indirect branch tracking
|
||||
--------------------------------------------------
|
||||
|
||||
@@ -12,8 +12,8 @@ maintainers:
|
||||
- Baojun Xu <baojun.xu@ti.com>
|
||||
|
||||
description: >
|
||||
The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or
|
||||
use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL,
|
||||
The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or
|
||||
use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL,
|
||||
the PDM reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK.
|
||||
|
||||
For system integration the dt-bindings/sound/tas2552.h header file provides
|
||||
@@ -34,6 +34,9 @@ properties:
|
||||
maxItems: 1
|
||||
description: gpio pin to enable/disable the device
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@@ -41,7 +44,10 @@ required:
|
||||
- iovdd-supply
|
||||
- avdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
@@ -54,6 +60,7 @@ examples:
|
||||
audio-codec@41 {
|
||||
compatible = "ti,tas2552";
|
||||
reg = <0x41>;
|
||||
#sound-dai-cells = <0>;
|
||||
vbat-supply = <®_vbat>;
|
||||
iovdd-supply = <®_iovdd>;
|
||||
avdd-supply = <®_avdd>;
|
||||
|
||||
@@ -39,7 +39,7 @@ void set_active_shstk(struct task_struct *task, unsigned long shstk_addr);
|
||||
bool is_shstk_enabled(struct task_struct *task);
|
||||
bool is_shstk_locked(struct task_struct *task);
|
||||
bool is_shstk_allocated(struct task_struct *task);
|
||||
void set_shstk_lock(struct task_struct *task);
|
||||
void set_shstk_lock(struct task_struct *task, bool lock);
|
||||
void set_shstk_status(struct task_struct *task, bool enable);
|
||||
unsigned long get_active_shstk(struct task_struct *task);
|
||||
int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr);
|
||||
@@ -47,7 +47,7 @@ int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr);
|
||||
bool is_indir_lp_enabled(struct task_struct *task);
|
||||
bool is_indir_lp_locked(struct task_struct *task);
|
||||
void set_indir_lp_status(struct task_struct *task, bool enable);
|
||||
void set_indir_lp_lock(struct task_struct *task);
|
||||
void set_indir_lp_lock(struct task_struct *task, bool lock);
|
||||
|
||||
#define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE)
|
||||
|
||||
@@ -69,7 +69,7 @@ void set_indir_lp_lock(struct task_struct *task);
|
||||
|
||||
#define is_shstk_allocated(task) false
|
||||
|
||||
#define set_shstk_lock(task) do {} while (0)
|
||||
#define set_shstk_lock(task, lock) do {} while (0)
|
||||
|
||||
#define set_shstk_status(task, enable) do {} while (0)
|
||||
|
||||
@@ -79,7 +79,7 @@ void set_indir_lp_lock(struct task_struct *task);
|
||||
|
||||
#define set_indir_lp_status(task, enable) do {} while (0)
|
||||
|
||||
#define set_indir_lp_lock(task) do {} while (0)
|
||||
#define set_indir_lp_lock(task, lock) do {} while (0)
|
||||
|
||||
#define restore_user_shstk(tsk, shstk_ptr) -EINVAL
|
||||
|
||||
|
||||
@@ -132,26 +132,28 @@ struct __sc_riscv_cfi_state {
|
||||
unsigned long ss_ptr; /* shadow stack pointer */
|
||||
};
|
||||
|
||||
#define PTRACE_CFI_LP_EN_BIT 0
|
||||
#define PTRACE_CFI_LP_LOCK_BIT 1
|
||||
#define PTRACE_CFI_ELP_BIT 2
|
||||
#define PTRACE_CFI_SS_EN_BIT 3
|
||||
#define PTRACE_CFI_SS_LOCK_BIT 4
|
||||
#define PTRACE_CFI_SS_PTR_BIT 5
|
||||
#define PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT 0
|
||||
#define PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT 1
|
||||
#define PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT 2
|
||||
#define PTRACE_CFI_SHADOW_STACK_EN_BIT 3
|
||||
#define PTRACE_CFI_SHADOW_STACK_LOCK_BIT 4
|
||||
#define PTRACE_CFI_SHADOW_STACK_PTR_BIT 5
|
||||
|
||||
#define PTRACE_CFI_LP_EN_STATE _BITUL(PTRACE_CFI_LP_EN_BIT)
|
||||
#define PTRACE_CFI_LP_LOCK_STATE _BITUL(PTRACE_CFI_LP_LOCK_BIT)
|
||||
#define PTRACE_CFI_ELP_STATE _BITUL(PTRACE_CFI_ELP_BIT)
|
||||
#define PTRACE_CFI_SS_EN_STATE _BITUL(PTRACE_CFI_SS_EN_BIT)
|
||||
#define PTRACE_CFI_SS_LOCK_STATE _BITUL(PTRACE_CFI_SS_LOCK_BIT)
|
||||
#define PTRACE_CFI_SS_PTR_STATE _BITUL(PTRACE_CFI_SS_PTR_BIT)
|
||||
#define PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE _BITUL(PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT)
|
||||
#define PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE \
|
||||
_BITUL(PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT)
|
||||
#define PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE \
|
||||
_BITUL(PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT)
|
||||
#define PTRACE_CFI_SHADOW_STACK_EN_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_EN_BIT)
|
||||
#define PTRACE_CFI_SHADOW_STACK_LOCK_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_LOCK_BIT)
|
||||
#define PTRACE_CFI_SHADOW_STACK_PTR_STATE _BITUL(PTRACE_CFI_SHADOW_STACK_PTR_BIT)
|
||||
|
||||
#define PRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_LP_EN_STATE | \
|
||||
PTRACE_CFI_LP_LOCK_STATE | \
|
||||
PTRACE_CFI_ELP_STATE | \
|
||||
PTRACE_CFI_SS_EN_STATE | \
|
||||
PTRACE_CFI_SS_LOCK_STATE | \
|
||||
PTRACE_CFI_SS_PTR_STATE)
|
||||
#define PTRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | \
|
||||
PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE | \
|
||||
PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE | \
|
||||
PTRACE_CFI_SHADOW_STACK_EN_STATE | \
|
||||
PTRACE_CFI_SHADOW_STACK_LOCK_STATE | \
|
||||
PTRACE_CFI_SHADOW_STACK_PTR_STATE)
|
||||
|
||||
struct __cfi_status {
|
||||
__u64 cfi_state;
|
||||
|
||||
@@ -160,6 +160,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
|
||||
* clear shadow stack state on exec.
|
||||
* libc will set it later via prctl.
|
||||
*/
|
||||
set_shstk_lock(current, false);
|
||||
set_shstk_status(current, false);
|
||||
set_shstk_base(current, 0, 0);
|
||||
set_active_shstk(current, 0);
|
||||
@@ -167,6 +168,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc,
|
||||
* disable indirect branch tracking on exec.
|
||||
* libc will enable it later via prctl.
|
||||
*/
|
||||
set_indir_lp_lock(current, false);
|
||||
set_indir_lp_status(current, false);
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
+11
-11
@@ -303,18 +303,18 @@ static int riscv_cfi_get(struct task_struct *target,
|
||||
regs = task_pt_regs(target);
|
||||
|
||||
if (is_indir_lp_enabled(target)) {
|
||||
user_cfi.cfi_status.cfi_state |= PTRACE_CFI_LP_EN_STATE;
|
||||
user_cfi.cfi_status.cfi_state |= PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE;
|
||||
user_cfi.cfi_status.cfi_state |= is_indir_lp_locked(target) ?
|
||||
PTRACE_CFI_LP_LOCK_STATE : 0;
|
||||
PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE : 0;
|
||||
user_cfi.cfi_status.cfi_state |= (regs->status & SR_ELP) ?
|
||||
PTRACE_CFI_ELP_STATE : 0;
|
||||
PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE : 0;
|
||||
}
|
||||
|
||||
if (is_shstk_enabled(target)) {
|
||||
user_cfi.cfi_status.cfi_state |= (PTRACE_CFI_SS_EN_STATE |
|
||||
PTRACE_CFI_SS_PTR_STATE);
|
||||
user_cfi.cfi_status.cfi_state |= (PTRACE_CFI_SHADOW_STACK_EN_STATE |
|
||||
PTRACE_CFI_SHADOW_STACK_PTR_STATE);
|
||||
user_cfi.cfi_status.cfi_state |= is_shstk_locked(target) ?
|
||||
PTRACE_CFI_SS_LOCK_STATE : 0;
|
||||
PTRACE_CFI_SHADOW_STACK_LOCK_STATE : 0;
|
||||
user_cfi.shstk_ptr = get_active_shstk(target);
|
||||
}
|
||||
|
||||
@@ -349,15 +349,15 @@ static int riscv_cfi_set(struct task_struct *target,
|
||||
* rsvd field should be set to zero so that if those fields are needed in future
|
||||
*/
|
||||
if ((user_cfi.cfi_status.cfi_state &
|
||||
(PTRACE_CFI_LP_EN_STATE | PTRACE_CFI_LP_LOCK_STATE |
|
||||
PTRACE_CFI_SS_EN_STATE | PTRACE_CFI_SS_LOCK_STATE)) ||
|
||||
(user_cfi.cfi_status.cfi_state & PRACE_CFI_STATE_INVALID_MASK))
|
||||
(PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE |
|
||||
PTRACE_CFI_SHADOW_STACK_EN_STATE | PTRACE_CFI_SHADOW_STACK_LOCK_STATE)) ||
|
||||
(user_cfi.cfi_status.cfi_state & PTRACE_CFI_STATE_INVALID_MASK))
|
||||
return -EINVAL;
|
||||
|
||||
/* If lpad is enabled on target and ptrace requests to set / clear elp, do that */
|
||||
if (is_indir_lp_enabled(target)) {
|
||||
if (user_cfi.cfi_status.cfi_state &
|
||||
PTRACE_CFI_ELP_STATE) /* set elp state */
|
||||
PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE) /* set elp state */
|
||||
regs->status |= SR_ELP;
|
||||
else
|
||||
regs->status &= ~SR_ELP; /* clear elp state */
|
||||
@@ -365,7 +365,7 @@ static int riscv_cfi_set(struct task_struct *target,
|
||||
|
||||
/* If shadow stack enabled on target, set new shadow stack pointer */
|
||||
if (is_shstk_enabled(target) &&
|
||||
(user_cfi.cfi_status.cfi_state & PTRACE_CFI_SS_PTR_STATE))
|
||||
(user_cfi.cfi_status.cfi_state & PTRACE_CFI_SHADOW_STACK_PTR_STATE))
|
||||
set_active_shstk(target, user_cfi.shstk_ptr);
|
||||
|
||||
return 0;
|
||||
|
||||
+19
-20
@@ -74,9 +74,9 @@ void set_shstk_status(struct task_struct *task, bool enable)
|
||||
csr_write(CSR_ENVCFG, task->thread.envcfg);
|
||||
}
|
||||
|
||||
void set_shstk_lock(struct task_struct *task)
|
||||
void set_shstk_lock(struct task_struct *task, bool lock)
|
||||
{
|
||||
task->thread_info.user_cfi_state.ubcfi_locked = 1;
|
||||
task->thread_info.user_cfi_state.ubcfi_locked = lock;
|
||||
}
|
||||
|
||||
bool is_indir_lp_enabled(struct task_struct *task)
|
||||
@@ -104,9 +104,9 @@ void set_indir_lp_status(struct task_struct *task, bool enable)
|
||||
csr_write(CSR_ENVCFG, task->thread.envcfg);
|
||||
}
|
||||
|
||||
void set_indir_lp_lock(struct task_struct *task)
|
||||
void set_indir_lp_lock(struct task_struct *task, bool lock)
|
||||
{
|
||||
task->thread_info.user_cfi_state.ufcfi_locked = 1;
|
||||
task->thread_info.user_cfi_state.ufcfi_locked = lock;
|
||||
}
|
||||
/*
|
||||
* If size is 0, then to be compatible with regular stack we want it to be as big as
|
||||
@@ -452,28 +452,27 @@ int arch_lock_shadow_stack_status(struct task_struct *task,
|
||||
!is_shstk_enabled(task) || arg != 0)
|
||||
return -EINVAL;
|
||||
|
||||
set_shstk_lock(task);
|
||||
set_shstk_lock(task, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status)
|
||||
int arch_prctl_get_branch_landing_pad_state(struct task_struct *t,
|
||||
unsigned long __user *state)
|
||||
{
|
||||
unsigned long fcfi_status = 0;
|
||||
|
||||
if (!is_user_lpad_enabled())
|
||||
return -EINVAL;
|
||||
|
||||
/* indirect branch tracking is enabled on the task or not */
|
||||
fcfi_status |= (is_indir_lp_enabled(t) ? PR_INDIR_BR_LP_ENABLE : 0);
|
||||
fcfi_status = (is_indir_lp_enabled(t) ? PR_CFI_ENABLE : PR_CFI_DISABLE);
|
||||
fcfi_status |= (is_indir_lp_locked(t) ? PR_CFI_LOCK : 0);
|
||||
|
||||
return copy_to_user(status, &fcfi_status, sizeof(fcfi_status)) ? -EFAULT : 0;
|
||||
return copy_to_user(state, &fcfi_status, sizeof(fcfi_status)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status)
|
||||
int arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long state)
|
||||
{
|
||||
bool enable_indir_lp = false;
|
||||
|
||||
if (!is_user_lpad_enabled())
|
||||
return -EINVAL;
|
||||
|
||||
@@ -481,28 +480,28 @@ int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status)
|
||||
if (is_indir_lp_locked(t))
|
||||
return -EINVAL;
|
||||
|
||||
/* Reject unknown flags */
|
||||
if (status & ~PR_INDIR_BR_LP_ENABLE)
|
||||
if (!(state & (PR_CFI_ENABLE | PR_CFI_DISABLE)))
|
||||
return -EINVAL;
|
||||
|
||||
enable_indir_lp = (status & PR_INDIR_BR_LP_ENABLE);
|
||||
set_indir_lp_status(t, enable_indir_lp);
|
||||
if (state & PR_CFI_ENABLE && state & PR_CFI_DISABLE)
|
||||
return -EINVAL;
|
||||
|
||||
set_indir_lp_status(t, !!(state & PR_CFI_ENABLE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_lock_indir_br_lp_status(struct task_struct *task,
|
||||
unsigned long arg)
|
||||
int arch_prctl_lock_branch_landing_pad_state(struct task_struct *task)
|
||||
{
|
||||
/*
|
||||
* If indirect branch tracking is not supported or not enabled on task,
|
||||
* nothing to lock here
|
||||
*/
|
||||
if (!is_user_lpad_enabled() ||
|
||||
!is_indir_lp_enabled(task) || arg != 0)
|
||||
!is_indir_lp_enabled(task))
|
||||
return -EINVAL;
|
||||
|
||||
set_indir_lp_lock(task);
|
||||
set_indir_lp_lock(task, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ config DRM_ACCEL_ARM_ETHOSU
|
||||
tristate "Arm Ethos-U65/U85 NPU"
|
||||
depends on HAS_IOMEM
|
||||
depends on DRM_ACCEL
|
||||
depends on ARM || ARM64 || COMPILE_TEST
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select DRM_SCHED
|
||||
select GENERIC_ALLOCATOR
|
||||
|
||||
@@ -127,7 +127,7 @@ static const struct kobj_type class_ktype = {
|
||||
};
|
||||
|
||||
int class_create_file_ns(const struct class *cls, const struct class_attribute *attr,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
struct subsys_private *sp = class_to_subsys(cls);
|
||||
int error;
|
||||
@@ -143,7 +143,7 @@ int class_create_file_ns(const struct class *cls, const struct class_attribute *
|
||||
EXPORT_SYMBOL_GPL(class_create_file_ns);
|
||||
|
||||
void class_remove_file_ns(const struct class *cls, const struct class_attribute *attr,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
struct subsys_private *sp = class_to_subsys(cls);
|
||||
|
||||
|
||||
+3
-4
@@ -2570,15 +2570,14 @@ static void device_release(struct kobject *kobj)
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
static const void *device_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *device_namespace(const struct kobject *kobj)
|
||||
{
|
||||
const struct device *dev = kobj_to_dev(kobj);
|
||||
const void *ns = NULL;
|
||||
|
||||
if (dev->class && dev->class->namespace)
|
||||
ns = dev->class->namespace(dev);
|
||||
return dev->class->namespace(dev);
|
||||
|
||||
return ns;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void device_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
|
||||
|
||||
@@ -60,7 +60,7 @@ extern __weak const efi_config_table_type_t efi_arch_tables[];
|
||||
* x86 defines its own instance of sysfb_primary_display and uses
|
||||
* it even without EFI, everything else can get them from here.
|
||||
*/
|
||||
#if !defined(CONFIG_X86) && (defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON)) || defined(CONFIG_FIRMWARE_EDID)
|
||||
#if !defined(CONFIG_X86) && (defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON) || defined(CONFIG_FIRMWARE_EDID))
|
||||
struct sysfb_display_info sysfb_primary_display __section(".data");
|
||||
EXPORT_SYMBOL_GPL(sysfb_primary_display);
|
||||
#endif
|
||||
|
||||
@@ -256,6 +256,8 @@ static int gpo_bd72720_probe(struct platform_device *pdev)
|
||||
g->dev = dev;
|
||||
g->chip.parent = parent;
|
||||
g->regmap = dev_get_regmap(parent, NULL);
|
||||
if (!g->regmap)
|
||||
return -ENODEV;
|
||||
|
||||
return devm_gpiochip_add_data(dev, &g->chip, g);
|
||||
}
|
||||
|
||||
@@ -595,7 +595,7 @@ static void tegra_gpio_irq_release_resources(struct irq_data *d)
|
||||
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
|
||||
|
||||
gpiochip_relres_irq(chip, d->hwirq);
|
||||
tegra_gpio_enable(tgi, d->hwirq);
|
||||
tegra_gpio_disable(tgi, d->hwirq);
|
||||
}
|
||||
|
||||
static void tegra_gpio_irq_print_chip(struct irq_data *d, struct seq_file *s)
|
||||
@@ -698,7 +698,7 @@ static int tegra_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL);
|
||||
if (!tgi)
|
||||
return -ENODEV;
|
||||
return -ENOMEM;
|
||||
|
||||
tgi->soc = of_device_get_match_data(&pdev->dev);
|
||||
tgi->dev = &pdev->dev;
|
||||
|
||||
@@ -2678,9 +2678,9 @@ static u32 psr2_pipe_srcsz_early_tpt_calc(struct intel_crtc_state *crtc_state,
|
||||
|
||||
static void clip_area_update(struct drm_rect *overlap_damage_area,
|
||||
struct drm_rect *damage_area,
|
||||
struct drm_rect *pipe_src)
|
||||
struct drm_rect *display_area)
|
||||
{
|
||||
if (!drm_rect_intersect(damage_area, pipe_src))
|
||||
if (!drm_rect_intersect(damage_area, display_area))
|
||||
return;
|
||||
|
||||
if (overlap_damage_area->y1 == -1) {
|
||||
@@ -2731,6 +2731,7 @@ static bool intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_st
|
||||
static void
|
||||
intel_psr2_sel_fetch_et_alignment(struct intel_atomic_state *state,
|
||||
struct intel_crtc *crtc,
|
||||
struct drm_rect *display_area,
|
||||
bool *cursor_in_su_area)
|
||||
{
|
||||
struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
|
||||
@@ -2758,7 +2759,7 @@ intel_psr2_sel_fetch_et_alignment(struct intel_atomic_state *state,
|
||||
continue;
|
||||
|
||||
clip_area_update(&crtc_state->psr2_su_area, &new_plane_state->uapi.dst,
|
||||
&crtc_state->pipe_src);
|
||||
display_area);
|
||||
*cursor_in_su_area = true;
|
||||
}
|
||||
}
|
||||
@@ -2855,6 +2856,12 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
|
||||
struct intel_plane_state *new_plane_state, *old_plane_state;
|
||||
struct intel_plane *plane;
|
||||
struct drm_rect display_area = {
|
||||
.x1 = 0,
|
||||
.y1 = 0,
|
||||
.x2 = crtc_state->hw.adjusted_mode.crtc_hdisplay,
|
||||
.y2 = crtc_state->hw.adjusted_mode.crtc_vdisplay,
|
||||
};
|
||||
bool full_update = false, su_area_changed;
|
||||
int i, ret;
|
||||
|
||||
@@ -2868,7 +2875,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
|
||||
crtc_state->psr2_su_area.x1 = 0;
|
||||
crtc_state->psr2_su_area.y1 = -1;
|
||||
crtc_state->psr2_su_area.x2 = drm_rect_width(&crtc_state->pipe_src);
|
||||
crtc_state->psr2_su_area.x2 = drm_rect_width(&display_area);
|
||||
crtc_state->psr2_su_area.y2 = -1;
|
||||
|
||||
/*
|
||||
@@ -2906,14 +2913,14 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
damaged_area.y1 = old_plane_state->uapi.dst.y1;
|
||||
damaged_area.y2 = old_plane_state->uapi.dst.y2;
|
||||
clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
|
||||
&crtc_state->pipe_src);
|
||||
&display_area);
|
||||
}
|
||||
|
||||
if (new_plane_state->uapi.visible) {
|
||||
damaged_area.y1 = new_plane_state->uapi.dst.y1;
|
||||
damaged_area.y2 = new_plane_state->uapi.dst.y2;
|
||||
clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
|
||||
&crtc_state->pipe_src);
|
||||
&display_area);
|
||||
}
|
||||
continue;
|
||||
} else if (new_plane_state->uapi.alpha != old_plane_state->uapi.alpha) {
|
||||
@@ -2921,7 +2928,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
damaged_area.y1 = new_plane_state->uapi.dst.y1;
|
||||
damaged_area.y2 = new_plane_state->uapi.dst.y2;
|
||||
clip_area_update(&crtc_state->psr2_su_area, &damaged_area,
|
||||
&crtc_state->pipe_src);
|
||||
&display_area);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2937,7 +2944,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
damaged_area.x1 += new_plane_state->uapi.dst.x1 - src.x1;
|
||||
damaged_area.x2 += new_plane_state->uapi.dst.x1 - src.x1;
|
||||
|
||||
clip_area_update(&crtc_state->psr2_su_area, &damaged_area, &crtc_state->pipe_src);
|
||||
clip_area_update(&crtc_state->psr2_su_area, &damaged_area, &display_area);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2972,7 +2979,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
* cursor is added into affected planes even when
|
||||
* cursor is not updated by itself.
|
||||
*/
|
||||
intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area);
|
||||
intel_psr2_sel_fetch_et_alignment(state, crtc, &display_area,
|
||||
&cursor_in_su_area);
|
||||
|
||||
su_area_changed = intel_psr2_sel_fetch_pipe_alignment(crtc_state);
|
||||
|
||||
@@ -3048,8 +3056,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
|
||||
|
||||
skip_sel_fetch_set_loop:
|
||||
if (full_update)
|
||||
clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src,
|
||||
&crtc_state->pipe_src);
|
||||
clip_area_update(&crtc_state->psr2_su_area, &display_area,
|
||||
&display_area);
|
||||
|
||||
psr2_man_trk_ctl_calc(crtc_state, full_update);
|
||||
crtc_state->pipe_srcsz_early_tpt =
|
||||
|
||||
@@ -896,7 +896,7 @@ static struct i915_vma *eb_lookup_vma(struct i915_execbuffer *eb, u32 handle)
|
||||
|
||||
rcu_read_lock();
|
||||
vma = radix_tree_lookup(&eb->gem_context->handles_vma, handle);
|
||||
if (likely(vma && vma->vm == vm))
|
||||
if (likely(vma))
|
||||
vma = i915_vma_tryget(vma);
|
||||
else
|
||||
vma = NULL;
|
||||
|
||||
@@ -148,10 +148,12 @@ static void heartbeat(struct work_struct *wrk)
|
||||
/* Just in case everything has gone horribly wrong, give it a kick */
|
||||
intel_engine_flush_submission(engine);
|
||||
|
||||
rq = engine->heartbeat.systole;
|
||||
if (rq && i915_request_completed(rq)) {
|
||||
i915_request_put(rq);
|
||||
engine->heartbeat.systole = NULL;
|
||||
rq = xchg(&engine->heartbeat.systole, NULL);
|
||||
if (rq) {
|
||||
if (i915_request_completed(rq))
|
||||
i915_request_put(rq);
|
||||
else
|
||||
engine->heartbeat.systole = rq;
|
||||
}
|
||||
|
||||
if (!intel_engine_pm_get_if_awake(engine))
|
||||
@@ -232,8 +234,11 @@ static void heartbeat(struct work_struct *wrk)
|
||||
unlock:
|
||||
mutex_unlock(&ce->timeline->mutex);
|
||||
out:
|
||||
if (!engine->i915->params.enable_hangcheck || !next_heartbeat(engine))
|
||||
i915_request_put(fetch_and_zero(&engine->heartbeat.systole));
|
||||
if (!engine->i915->params.enable_hangcheck || !next_heartbeat(engine)) {
|
||||
rq = xchg(&engine->heartbeat.systole, NULL);
|
||||
if (rq)
|
||||
i915_request_put(rq);
|
||||
}
|
||||
intel_engine_pm_put(engine);
|
||||
}
|
||||
|
||||
@@ -247,8 +252,13 @@ void intel_engine_unpark_heartbeat(struct intel_engine_cs *engine)
|
||||
|
||||
void intel_engine_park_heartbeat(struct intel_engine_cs *engine)
|
||||
{
|
||||
if (cancel_delayed_work(&engine->heartbeat.work))
|
||||
i915_request_put(fetch_and_zero(&engine->heartbeat.systole));
|
||||
if (cancel_delayed_work(&engine->heartbeat.work)) {
|
||||
struct i915_request *rq;
|
||||
|
||||
rq = xchg(&engine->heartbeat.systole, NULL);
|
||||
if (rq)
|
||||
i915_request_put(rq);
|
||||
}
|
||||
}
|
||||
|
||||
void intel_gt_unpark_heartbeats(struct intel_gt *gt)
|
||||
|
||||
@@ -738,12 +738,15 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&bo->madv_lock);
|
||||
if (bo->madv != VC4_MADV_WILLNEED) {
|
||||
DRM_DEBUG("mmapping of %s BO not allowed\n",
|
||||
bo->madv == VC4_MADV_DONTNEED ?
|
||||
"purgeable" : "purged");
|
||||
mutex_unlock(&bo->madv_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_unlock(&bo->madv_lock);
|
||||
|
||||
return drm_gem_dma_mmap(&bo->base, vma);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ vc4_free_hang_state(struct drm_device *dev, struct vc4_hang_state *state)
|
||||
for (i = 0; i < state->user_state.bo_count; i++)
|
||||
drm_gem_object_put(state->bo[i]);
|
||||
|
||||
kfree(state->bo);
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
@@ -170,10 +171,8 @@ vc4_save_hang_state(struct drm_device *dev)
|
||||
spin_lock_irqsave(&vc4->job_lock, irqflags);
|
||||
exec[0] = vc4_first_bin_job(vc4);
|
||||
exec[1] = vc4_first_render_job(vc4);
|
||||
if (!exec[0] && !exec[1]) {
|
||||
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
|
||||
return;
|
||||
}
|
||||
if (!exec[0] && !exec[1])
|
||||
goto err_free_state;
|
||||
|
||||
/* Get the bos from both binner and renderer into hang state. */
|
||||
state->bo_count = 0;
|
||||
@@ -190,10 +189,8 @@ vc4_save_hang_state(struct drm_device *dev)
|
||||
kernel_state->bo = kzalloc_objs(*kernel_state->bo, state->bo_count,
|
||||
GFP_ATOMIC);
|
||||
|
||||
if (!kernel_state->bo) {
|
||||
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
|
||||
return;
|
||||
}
|
||||
if (!kernel_state->bo)
|
||||
goto err_free_state;
|
||||
|
||||
k = 0;
|
||||
for (i = 0; i < 2; i++) {
|
||||
@@ -285,6 +282,12 @@ vc4_save_hang_state(struct drm_device *dev)
|
||||
vc4->hang_state = kernel_state;
|
||||
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_free_state:
|
||||
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
|
||||
kfree(kernel_state);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -481,6 +481,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -595,9 +595,8 @@ static void adjust_idledly(struct xe_hw_engine *hwe)
|
||||
maxcnt *= maxcnt_units_ns;
|
||||
|
||||
if (xe_gt_WARN_ON(gt, idledly >= maxcnt || inhibit_switch)) {
|
||||
idledly = DIV_ROUND_CLOSEST(((maxcnt - 1) * maxcnt_units_ns),
|
||||
idledly = DIV_ROUND_CLOSEST(((maxcnt - 1) * 1000),
|
||||
idledly_units_ps);
|
||||
idledly = DIV_ROUND_CLOSEST(idledly, 1000);
|
||||
xe_mmio_write32(>->mmio, RING_IDLEDLY(hwe->mmio_base), idledly);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,12 +509,13 @@ static int ib_device_uevent(const struct device *device,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const void *net_namespace(const struct device *d)
|
||||
static const struct ns_common *net_namespace(const struct device *d)
|
||||
{
|
||||
const struct ib_core_device *coredev =
|
||||
container_of(d, struct ib_core_device, dev);
|
||||
struct net *net = read_pnet(&coredev->rdma_net);
|
||||
|
||||
return read_pnet(&coredev->rdma_net);
|
||||
return net ? to_ns_common(net) : NULL;
|
||||
}
|
||||
|
||||
static struct class ib_class = {
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/inet.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <rdma/ib_cache.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
@@ -1048,7 +1049,7 @@ static void srp_remove_target(struct srp_target_port *target)
|
||||
scsi_remove_host(target->scsi_host);
|
||||
srp_stop_rport_timers(target->rport);
|
||||
srp_disconnect_target(target);
|
||||
kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
|
||||
kobj_ns_drop(KOBJ_NS_TYPE_NET, to_ns_common(target->net));
|
||||
for (i = 0; i < target->ch_count; i++) {
|
||||
ch = &target->ch[i];
|
||||
srp_free_ch_ib(target, ch);
|
||||
@@ -3713,7 +3714,7 @@ static ssize_t add_target_store(struct device *dev,
|
||||
|
||||
target = host_to_target(target_host);
|
||||
|
||||
target->net = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
|
||||
target->net = to_net_ns(kobj_ns_grab_current(KOBJ_NS_TYPE_NET));
|
||||
target->io_class = SRP_REV16A_IB_IO_CLASS;
|
||||
target->scsi_host = target_host;
|
||||
target->srp_host = host;
|
||||
@@ -3905,7 +3906,7 @@ put:
|
||||
* earlier in this function.
|
||||
*/
|
||||
if (target->state != SRP_TARGET_REMOVED)
|
||||
kobj_ns_drop(KOBJ_NS_TYPE_NET, target->net);
|
||||
kobj_ns_drop(KOBJ_NS_TYPE_NET, to_ns_common(target->net));
|
||||
scsi_host_put(target->scsi_host);
|
||||
}
|
||||
|
||||
|
||||
@@ -369,11 +369,14 @@ struct vub300_mmc_host {
|
||||
static void vub300_delete(struct kref *kref)
|
||||
{ /* kref callback - softirq */
|
||||
struct vub300_mmc_host *vub300 = kref_to_vub300_mmc_host(kref);
|
||||
struct mmc_host *mmc = vub300->mmc;
|
||||
|
||||
usb_free_urb(vub300->command_out_urb);
|
||||
vub300->command_out_urb = NULL;
|
||||
usb_free_urb(vub300->command_res_urb);
|
||||
vub300->command_res_urb = NULL;
|
||||
usb_put_dev(vub300->udev);
|
||||
mmc_free_host(mmc);
|
||||
/*
|
||||
* and hence also frees vub300
|
||||
* which is contained at the end of struct mmc
|
||||
@@ -2112,7 +2115,7 @@ static int vub300_probe(struct usb_interface *interface,
|
||||
goto error1;
|
||||
}
|
||||
/* this also allocates memory for our VUB300 mmc host device */
|
||||
mmc = devm_mmc_alloc_host(&udev->dev, sizeof(*vub300));
|
||||
mmc = mmc_alloc_host(sizeof(*vub300), &udev->dev);
|
||||
if (!mmc) {
|
||||
retval = -ENOMEM;
|
||||
dev_err(&udev->dev, "not enough memory for the mmc_host\n");
|
||||
@@ -2269,7 +2272,7 @@ static int vub300_probe(struct usb_interface *interface,
|
||||
dev_err(&vub300->udev->dev,
|
||||
"Could not find two sets of bulk-in/out endpoint pairs\n");
|
||||
retval = -EINVAL;
|
||||
goto error4;
|
||||
goto err_free_host;
|
||||
}
|
||||
retval =
|
||||
usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
|
||||
@@ -2278,14 +2281,14 @@ static int vub300_probe(struct usb_interface *interface,
|
||||
0x0000, 0x0000, &vub300->hc_info,
|
||||
sizeof(vub300->hc_info), 1000);
|
||||
if (retval < 0)
|
||||
goto error4;
|
||||
goto err_free_host;
|
||||
retval =
|
||||
usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
|
||||
SET_ROM_WAIT_STATES,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
firmware_rom_wait_states, 0x0000, NULL, 0, 1000);
|
||||
if (retval < 0)
|
||||
goto error4;
|
||||
goto err_free_host;
|
||||
dev_info(&vub300->udev->dev,
|
||||
"operating_mode = %s %s %d MHz %s %d byte USB packets\n",
|
||||
(mmc->caps & MMC_CAP_SDIO_IRQ) ? "IRQs" : "POLL",
|
||||
@@ -2300,7 +2303,7 @@ static int vub300_probe(struct usb_interface *interface,
|
||||
0x0000, 0x0000, &vub300->system_port_status,
|
||||
sizeof(vub300->system_port_status), 1000);
|
||||
if (retval < 0) {
|
||||
goto error4;
|
||||
goto err_free_host;
|
||||
} else if (sizeof(vub300->system_port_status) == retval) {
|
||||
vub300->card_present =
|
||||
(0x0001 & vub300->system_port_status.port_flags) ? 1 : 0;
|
||||
@@ -2308,7 +2311,7 @@ static int vub300_probe(struct usb_interface *interface,
|
||||
(0x0010 & vub300->system_port_status.port_flags) ? 1 : 0;
|
||||
} else {
|
||||
retval = -EINVAL;
|
||||
goto error4;
|
||||
goto err_free_host;
|
||||
}
|
||||
usb_set_intfdata(interface, vub300);
|
||||
INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread);
|
||||
@@ -2338,6 +2341,8 @@ static int vub300_probe(struct usb_interface *interface,
|
||||
return 0;
|
||||
error6:
|
||||
timer_delete_sync(&vub300->inactivity_timer);
|
||||
err_free_host:
|
||||
mmc_free_host(mmc);
|
||||
/*
|
||||
* and hence also frees vub300
|
||||
* which is contained at the end of struct mmc
|
||||
@@ -2365,8 +2370,8 @@ static void vub300_disconnect(struct usb_interface *interface)
|
||||
usb_set_intfdata(interface, NULL);
|
||||
/* prevent more I/O from starting */
|
||||
vub300->interface = NULL;
|
||||
kref_put(&vub300->kref, vub300_delete);
|
||||
mmc_remove_host(mmc);
|
||||
kref_put(&vub300->kref, vub300_delete);
|
||||
pr_info("USB vub300 remote SDIO host controller[%d]"
|
||||
" now disconnected", ifnum);
|
||||
return;
|
||||
|
||||
@@ -808,7 +808,7 @@ int __net_init bond_create_sysfs(struct bond_net *bn)
|
||||
sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
|
||||
|
||||
ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters,
|
||||
bn->net);
|
||||
to_ns_common(bn->net));
|
||||
/* Permit multiple loads of the module by ignoring failures to
|
||||
* create the bonding_masters sysfs file. Bonding devices
|
||||
* created by second or subsequent loads of the module will
|
||||
@@ -835,7 +835,7 @@ int __net_init bond_create_sysfs(struct bond_net *bn)
|
||||
/* Remove /sys/class/net/bonding_masters. */
|
||||
void __net_exit bond_destroy_sysfs(struct bond_net *bn)
|
||||
{
|
||||
netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net);
|
||||
netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, to_ns_common(bn->net));
|
||||
}
|
||||
|
||||
/* Initialize sysfs for each bond. This sets up and registers
|
||||
|
||||
@@ -30,10 +30,11 @@
|
||||
static dev_t ipvtap_major;
|
||||
static struct cdev ipvtap_cdev;
|
||||
|
||||
static const void *ipvtap_net_namespace(const struct device *d)
|
||||
static const struct ns_common *ipvtap_net_namespace(const struct device *d)
|
||||
{
|
||||
const struct net_device *dev = to_net_dev(d->parent);
|
||||
return dev_net(dev);
|
||||
|
||||
return to_ns_common(dev_net(dev));
|
||||
}
|
||||
|
||||
static struct class ipvtap_class = {
|
||||
|
||||
@@ -35,10 +35,11 @@ struct macvtap_dev {
|
||||
*/
|
||||
static dev_t macvtap_major;
|
||||
|
||||
static const void *macvtap_net_namespace(const struct device *d)
|
||||
static const struct ns_common *macvtap_net_namespace(const struct device *d)
|
||||
{
|
||||
const struct net_device *dev = to_net_dev(d->parent);
|
||||
return dev_net(dev);
|
||||
|
||||
return to_ns_common(dev_net(dev));
|
||||
}
|
||||
|
||||
static struct class macvtap_class = {
|
||||
|
||||
@@ -53,8 +53,6 @@
|
||||
#define PADOWN_MASK(p) (GENMASK(3, 0) << PADOWN_SHIFT(p))
|
||||
#define PADOWN_GPP(p) ((p) / 8)
|
||||
|
||||
#define PWMC 0x204
|
||||
|
||||
/* Offset from pad_regs */
|
||||
#define PADCFG0 0x000
|
||||
#define PADCFG0_RXEVCFG_MASK GENMASK(26, 25)
|
||||
@@ -205,19 +203,25 @@ static bool intel_pad_owned_by_host(const struct intel_pinctrl *pctrl, unsigned
|
||||
community = intel_get_community(pctrl, pin);
|
||||
if (!community)
|
||||
return false;
|
||||
if (!community->padown_offset)
|
||||
|
||||
/* If padown_offset is not provided, assume host ownership */
|
||||
padown = community->regs + community->padown_offset;
|
||||
if (padown == community->regs)
|
||||
return true;
|
||||
|
||||
/* New HW generations have extended PAD_OWN registers */
|
||||
if (community->features & PINCTRL_FEATURE_3BIT_PAD_OWN)
|
||||
return !(readl(padown + pin_to_padno(community, pin) * 4) & 7);
|
||||
|
||||
padgrp = intel_community_get_padgroup(community, pin);
|
||||
if (!padgrp)
|
||||
return false;
|
||||
|
||||
gpp_offset = padgroup_offset(padgrp, pin);
|
||||
gpp = PADOWN_GPP(gpp_offset);
|
||||
offset = community->padown_offset + padgrp->padown_num * 4 + gpp * 4;
|
||||
padown = community->regs + offset;
|
||||
offset = padgrp->padown_num * 4 + gpp * 4;
|
||||
|
||||
return !(readl(padown) & PADOWN_MASK(gpp_offset));
|
||||
return !(readl(padown + offset) & PADOWN_MASK(gpp_offset));
|
||||
}
|
||||
|
||||
static bool intel_pad_acpi_mode(const struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
@@ -1549,8 +1553,10 @@ static int intel_pinctrl_pm_init(struct intel_pinctrl *pctrl)
|
||||
}
|
||||
|
||||
static int intel_pinctrl_probe_pwm(struct intel_pinctrl *pctrl,
|
||||
struct intel_community *community)
|
||||
struct intel_community *community,
|
||||
unsigned short capability_offset)
|
||||
{
|
||||
void __iomem *base = community->regs + capability_offset + 4;
|
||||
static const struct pwm_lpss_boardinfo info = {
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 1,
|
||||
@@ -1564,7 +1570,7 @@ static int intel_pinctrl_probe_pwm(struct intel_pinctrl *pctrl,
|
||||
if (!IS_REACHABLE(CONFIG_PWM_LPSS))
|
||||
return 0;
|
||||
|
||||
chip = devm_pwm_lpss_probe(pctrl->dev, community->regs + PWMC, &info);
|
||||
chip = devm_pwm_lpss_probe(pctrl->dev, base, &info);
|
||||
return PTR_ERR_OR_ZERO(chip);
|
||||
}
|
||||
|
||||
@@ -1595,7 +1601,9 @@ int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
struct intel_community *community = &pctrl->communities[i];
|
||||
unsigned short capability_offset[6];
|
||||
void __iomem *regs;
|
||||
u32 revision;
|
||||
u32 offset;
|
||||
u32 value;
|
||||
|
||||
@@ -1610,10 +1618,14 @@ int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
value = readl(regs + REVID);
|
||||
if (value == ~0u)
|
||||
return -ENODEV;
|
||||
if (((value & REVID_MASK) >> REVID_SHIFT) >= 0x94) {
|
||||
|
||||
revision = (value & REVID_MASK) >> REVID_SHIFT;
|
||||
if (revision >= 0x092) {
|
||||
community->features |= PINCTRL_FEATURE_DEBOUNCE;
|
||||
community->features |= PINCTRL_FEATURE_1K_PD;
|
||||
}
|
||||
if (revision >= 0x110)
|
||||
community->features |= PINCTRL_FEATURE_3BIT_PAD_OWN;
|
||||
|
||||
/* Determine community features based on the capabilities */
|
||||
offset = CAPLIST;
|
||||
@@ -1622,15 +1634,19 @@ int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
switch ((value & CAPLIST_ID_MASK) >> CAPLIST_ID_SHIFT) {
|
||||
case CAPLIST_ID_GPIO_HW_INFO:
|
||||
community->features |= PINCTRL_FEATURE_GPIO_HW_INFO;
|
||||
capability_offset[CAPLIST_ID_GPIO_HW_INFO] = offset;
|
||||
break;
|
||||
case CAPLIST_ID_PWM:
|
||||
community->features |= PINCTRL_FEATURE_PWM;
|
||||
capability_offset[CAPLIST_ID_PWM] = offset;
|
||||
break;
|
||||
case CAPLIST_ID_BLINK:
|
||||
community->features |= PINCTRL_FEATURE_BLINK;
|
||||
capability_offset[CAPLIST_ID_BLINK] = offset;
|
||||
break;
|
||||
case CAPLIST_ID_EXP:
|
||||
community->features |= PINCTRL_FEATURE_EXP;
|
||||
capability_offset[CAPLIST_ID_EXP] = offset;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1653,7 +1669,7 @@ int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = intel_pinctrl_probe_pwm(pctrl, community);
|
||||
ret = intel_pinctrl_probe_pwm(pctrl, community, capability_offset[CAPLIST_ID_PWM]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ struct intel_community {
|
||||
#define PINCTRL_FEATURE_PWM BIT(3)
|
||||
#define PINCTRL_FEATURE_BLINK BIT(4)
|
||||
#define PINCTRL_FEATURE_EXP BIT(5)
|
||||
#define PINCTRL_FEATURE_3BIT_PAD_OWN BIT(6)
|
||||
|
||||
#define __INTEL_COMMUNITY(b, s, e, g, n, gs, gn, soc) \
|
||||
{ \
|
||||
|
||||
@@ -664,6 +664,15 @@ int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
|
||||
if (mcp->irq && mcp->irq_controller) {
|
||||
struct gpio_irq_chip *girq = &mcp->chip.irq;
|
||||
|
||||
/*
|
||||
* Disable all pin interrupts, to prevent the interrupt handler from
|
||||
* calling nested handlers for any currently-enabled interrupts that
|
||||
* do not (yet) have an actual handler.
|
||||
*/
|
||||
ret = mcp_write(mcp, MCP_GPINTEN, 0);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "can't disable interrupts\n");
|
||||
|
||||
gpio_irq_chip_set_chip(girq, &mcp23s08_irq_chip);
|
||||
/* This will let us handle the parent IRQ in the driver */
|
||||
girq->parent_handler = NULL;
|
||||
|
||||
@@ -810,6 +810,11 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
|
||||
if (ret < 0)
|
||||
goto error_unlock;
|
||||
|
||||
/*
|
||||
* cachefiles_bury_object() expects 2 references to 'victim',
|
||||
* and drops one.
|
||||
*/
|
||||
dget(victim);
|
||||
ret = cachefiles_bury_object(cache, NULL, dir, victim,
|
||||
FSCACHE_OBJECT_WAS_CULLED);
|
||||
dput(victim);
|
||||
|
||||
+5
-1
@@ -226,6 +226,9 @@ struct eventpoll {
|
||||
*/
|
||||
refcount_t refcount;
|
||||
|
||||
/* used to defer freeing past ep_get_upwards_depth_proc() RCU walk */
|
||||
struct rcu_head rcu;
|
||||
|
||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||
/* used to track busy poll napi_id */
|
||||
unsigned int napi_id;
|
||||
@@ -819,7 +822,8 @@ static void ep_free(struct eventpoll *ep)
|
||||
mutex_destroy(&ep->mtx);
|
||||
free_uid(ep->user);
|
||||
wakeup_source_unregister(ep->ws);
|
||||
kfree(ep);
|
||||
/* ep_get_upwards_depth_proc() may still hold epi->ep under RCU */
|
||||
kfree_rcu(ep, rcu);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+48
-20
@@ -14,6 +14,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/ns_common.h>
|
||||
|
||||
#include "kernfs-internal.h"
|
||||
|
||||
@@ -306,6 +307,18 @@ struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
|
||||
return parent;
|
||||
}
|
||||
|
||||
/*
|
||||
* kernfs_ns_id - return the namespace id for a given namespace
|
||||
* @ns: namespace tag (may be NULL)
|
||||
*
|
||||
* Use the 64-bit namespace id instead of raw pointers for hashing
|
||||
* and comparison to avoid leaking kernel addresses to userspace.
|
||||
*/
|
||||
static u64 kernfs_ns_id(const struct ns_common *ns)
|
||||
{
|
||||
return ns ? ns->ns_id : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* kernfs_name_hash - calculate hash of @ns + @name
|
||||
* @name: Null terminated string to hash
|
||||
@@ -313,9 +326,10 @@ struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
|
||||
*
|
||||
* Return: 31-bit hash of ns + name (so it fits in an off_t)
|
||||
*/
|
||||
static unsigned int kernfs_name_hash(const char *name, const void *ns)
|
||||
static unsigned int kernfs_name_hash(const char *name,
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
unsigned long hash = init_name_hash(ns);
|
||||
unsigned long hash = init_name_hash(kernfs_ns_id(ns));
|
||||
unsigned int len = strlen(name);
|
||||
while (len--)
|
||||
hash = partial_name_hash(*name++, hash);
|
||||
@@ -330,15 +344,18 @@ static unsigned int kernfs_name_hash(const char *name, const void *ns)
|
||||
}
|
||||
|
||||
static int kernfs_name_compare(unsigned int hash, const char *name,
|
||||
const void *ns, const struct kernfs_node *kn)
|
||||
const struct ns_common *ns, const struct kernfs_node *kn)
|
||||
{
|
||||
u64 ns_id = kernfs_ns_id(ns);
|
||||
u64 kn_ns_id = kernfs_ns_id(kn->ns);
|
||||
|
||||
if (hash < kn->hash)
|
||||
return -1;
|
||||
if (hash > kn->hash)
|
||||
return 1;
|
||||
if (ns < kn->ns)
|
||||
if (ns_id < kn_ns_id)
|
||||
return -1;
|
||||
if (ns > kn->ns)
|
||||
if (ns_id > kn_ns_id)
|
||||
return 1;
|
||||
return strcmp(name, kernfs_rcu_name(kn));
|
||||
}
|
||||
@@ -856,7 +873,7 @@ out_unlock:
|
||||
*/
|
||||
static struct kernfs_node *kernfs_find_ns(struct kernfs_node *parent,
|
||||
const unsigned char *name,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
struct rb_node *node = parent->dir.children.rb_node;
|
||||
bool has_ns = kernfs_ns_enabled(parent);
|
||||
@@ -889,7 +906,7 @@ static struct kernfs_node *kernfs_find_ns(struct kernfs_node *parent,
|
||||
|
||||
static struct kernfs_node *kernfs_walk_ns(struct kernfs_node *parent,
|
||||
const unsigned char *path,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
ssize_t len;
|
||||
char *p, *name;
|
||||
@@ -930,7 +947,8 @@ static struct kernfs_node *kernfs_walk_ns(struct kernfs_node *parent,
|
||||
* Return: pointer to the found kernfs_node on success, %NULL on failure.
|
||||
*/
|
||||
struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent,
|
||||
const char *name, const void *ns)
|
||||
const char *name,
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
struct kernfs_root *root = kernfs_root(parent);
|
||||
@@ -956,7 +974,8 @@ EXPORT_SYMBOL_GPL(kernfs_find_and_get_ns);
|
||||
* Return: pointer to the found kernfs_node on success, %NULL on failure.
|
||||
*/
|
||||
struct kernfs_node *kernfs_walk_and_get_ns(struct kernfs_node *parent,
|
||||
const char *path, const void *ns)
|
||||
const char *path,
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
struct kernfs_root *root = kernfs_root(parent);
|
||||
@@ -1079,7 +1098,8 @@ struct kernfs_node *kernfs_root_to_node(struct kernfs_root *root)
|
||||
struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
|
||||
const char *name, umode_t mode,
|
||||
kuid_t uid, kgid_t gid,
|
||||
void *priv, const void *ns)
|
||||
void *priv,
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
int rc;
|
||||
@@ -1199,7 +1219,7 @@ static int kernfs_dop_revalidate(struct inode *dir, const struct qstr *name,
|
||||
|
||||
/* The kernfs node has been moved to a different namespace */
|
||||
if (parent && kernfs_ns_enabled(parent) &&
|
||||
kernfs_info(dentry->d_sb)->ns != kn->ns)
|
||||
kernfs_ns_id(kernfs_info(dentry->d_sb)->ns) != kernfs_ns_id(kn->ns))
|
||||
goto out_bad;
|
||||
|
||||
up_read(&root->kernfs_rwsem);
|
||||
@@ -1221,7 +1241,7 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
|
||||
struct kernfs_node *kn;
|
||||
struct kernfs_root *root;
|
||||
struct inode *inode = NULL;
|
||||
const void *ns = NULL;
|
||||
const struct ns_common *ns = NULL;
|
||||
|
||||
root = kernfs_root(parent);
|
||||
down_read(&root->kernfs_rwsem);
|
||||
@@ -1702,7 +1722,7 @@ bool kernfs_remove_self(struct kernfs_node *kn)
|
||||
* Return: %0 on success, -ENOENT if such entry doesn't exist.
|
||||
*/
|
||||
int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
struct kernfs_root *root;
|
||||
@@ -1741,7 +1761,7 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
|
||||
* Return: %0 on success, -errno on failure.
|
||||
*/
|
||||
int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
|
||||
const char *new_name, const void *new_ns)
|
||||
const char *new_name, const struct ns_common *new_ns)
|
||||
{
|
||||
struct kernfs_node *old_parent;
|
||||
struct kernfs_root *root;
|
||||
@@ -1771,7 +1791,8 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
|
||||
old_name = kernfs_rcu_name(kn);
|
||||
if (!new_name)
|
||||
new_name = old_name;
|
||||
if ((old_parent == new_parent) && (kn->ns == new_ns) &&
|
||||
if ((old_parent == new_parent) &&
|
||||
(kernfs_ns_id(kn->ns) == kernfs_ns_id(new_ns)) &&
|
||||
(strcmp(old_name, new_name) == 0))
|
||||
goto out; /* nothing to rename */
|
||||
|
||||
@@ -1832,7 +1853,7 @@ static int kernfs_dir_fop_release(struct inode *inode, struct file *filp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct kernfs_node *kernfs_dir_pos(const void *ns,
|
||||
static struct kernfs_node *kernfs_dir_pos(const struct ns_common *ns,
|
||||
struct kernfs_node *parent, loff_t hash, struct kernfs_node *pos)
|
||||
{
|
||||
if (pos) {
|
||||
@@ -1845,6 +1866,7 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns,
|
||||
}
|
||||
if (!pos && (hash > 1) && (hash < INT_MAX)) {
|
||||
struct rb_node *node = parent->dir.children.rb_node;
|
||||
u64 ns_id = kernfs_ns_id(ns);
|
||||
while (node) {
|
||||
pos = rb_to_kn(node);
|
||||
|
||||
@@ -1852,12 +1874,17 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns,
|
||||
node = node->rb_left;
|
||||
else if (hash > pos->hash)
|
||||
node = node->rb_right;
|
||||
else if (ns_id < kernfs_ns_id(pos->ns))
|
||||
node = node->rb_left;
|
||||
else if (ns_id > kernfs_ns_id(pos->ns))
|
||||
node = node->rb_right;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Skip over entries which are dying/dead or in the wrong namespace */
|
||||
while (pos && (!kernfs_active(pos) || pos->ns != ns)) {
|
||||
while (pos && (!kernfs_active(pos) ||
|
||||
kernfs_ns_id(pos->ns) != kernfs_ns_id(ns))) {
|
||||
struct rb_node *node = rb_next(&pos->rb);
|
||||
if (!node)
|
||||
pos = NULL;
|
||||
@@ -1867,7 +1894,7 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns,
|
||||
return pos;
|
||||
}
|
||||
|
||||
static struct kernfs_node *kernfs_dir_next_pos(const void *ns,
|
||||
static struct kernfs_node *kernfs_dir_next_pos(const struct ns_common *ns,
|
||||
struct kernfs_node *parent, ino_t ino, struct kernfs_node *pos)
|
||||
{
|
||||
pos = kernfs_dir_pos(ns, parent, ino, pos);
|
||||
@@ -1878,7 +1905,8 @@ static struct kernfs_node *kernfs_dir_next_pos(const void *ns,
|
||||
pos = NULL;
|
||||
else
|
||||
pos = rb_to_kn(node);
|
||||
} while (pos && (!kernfs_active(pos) || pos->ns != ns));
|
||||
} while (pos && (!kernfs_active(pos) ||
|
||||
kernfs_ns_id(pos->ns) != kernfs_ns_id(ns)));
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
@@ -1889,7 +1917,7 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
|
||||
struct kernfs_node *parent = kernfs_dentry_node(dentry);
|
||||
struct kernfs_node *pos = file->private_data;
|
||||
struct kernfs_root *root;
|
||||
const void *ns = NULL;
|
||||
const struct ns_common *ns = NULL;
|
||||
|
||||
if (!dir_emit_dots(file, ctx))
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -1045,7 +1045,7 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
|
||||
umode_t mode, kuid_t uid, kgid_t gid,
|
||||
loff_t size,
|
||||
const struct kernfs_ops *ops,
|
||||
void *priv, const void *ns,
|
||||
void *priv, const struct ns_common *ns,
|
||||
struct lock_class_key *key)
|
||||
{
|
||||
struct kernfs_node *kn;
|
||||
|
||||
@@ -97,7 +97,7 @@ struct kernfs_super_info {
|
||||
* instance. If multiple tags become necessary, make the following
|
||||
* an array and compare kernfs_node tag against every entry.
|
||||
*/
|
||||
const void *ns;
|
||||
const struct ns_common *ns;
|
||||
|
||||
/* anchored at kernfs_root->supers, protected by kernfs_rwsem */
|
||||
struct list_head node;
|
||||
|
||||
+1
-1
@@ -345,7 +345,7 @@ static int kernfs_set_super(struct super_block *sb, struct fs_context *fc)
|
||||
*
|
||||
* Return: the namespace tag associated with kernfs super_block @sb.
|
||||
*/
|
||||
const void *kernfs_super_ns(struct super_block *sb)
|
||||
const struct ns_common *kernfs_super_ns(struct super_block *sb)
|
||||
{
|
||||
struct kernfs_super_info *info = kernfs_info(sb);
|
||||
|
||||
|
||||
+10
-6
@@ -11,6 +11,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/lockd/lockd.h>
|
||||
|
||||
@@ -127,9 +128,10 @@ static void nfs_netns_client_release(struct kobject *kobj)
|
||||
kfree(rcu_dereference_raw(c->identifier));
|
||||
}
|
||||
|
||||
static const void *nfs_netns_client_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *nfs_netns_client_namespace(const struct kobject *kobj)
|
||||
{
|
||||
return container_of(kobj, struct nfs_netns_client, kobject)->net;
|
||||
return to_ns_common(container_of(kobj, struct nfs_netns_client,
|
||||
kobject)->net);
|
||||
}
|
||||
|
||||
static struct kobj_attribute nfs_netns_client_id = __ATTR(identifier,
|
||||
@@ -156,9 +158,10 @@ static void nfs_netns_object_release(struct kobject *kobj)
|
||||
kfree(c);
|
||||
}
|
||||
|
||||
static const void *nfs_netns_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *nfs_netns_namespace(const struct kobject *kobj)
|
||||
{
|
||||
return container_of(kobj, struct nfs_netns_client, nfs_net_kobj)->net;
|
||||
return to_ns_common(container_of(kobj, struct nfs_netns_client,
|
||||
nfs_net_kobj)->net);
|
||||
}
|
||||
|
||||
static struct kobj_type nfs_netns_object_type = {
|
||||
@@ -350,9 +353,10 @@ static void nfs_sysfs_sb_release(struct kobject *kobj)
|
||||
/* no-op: why? see lib/kobject.c kobject_cleanup() */
|
||||
}
|
||||
|
||||
static const void *nfs_netns_server_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *nfs_netns_server_namespace(const struct kobject *kobj)
|
||||
{
|
||||
return container_of(kobj, struct nfs_server, kobj)->nfs_client->cl_net;
|
||||
return to_ns_common(container_of(kobj, struct nfs_server,
|
||||
kobj)->nfs_client->cl_net);
|
||||
}
|
||||
|
||||
static struct kobj_type nfs_sb_ktype = {
|
||||
|
||||
+3
-3
@@ -37,7 +37,7 @@ void sysfs_warn_dup(struct kernfs_node *parent, const char *name)
|
||||
* @kobj: object we're creating directory for
|
||||
* @ns: the namespace tag to use
|
||||
*/
|
||||
int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
|
||||
int sysfs_create_dir_ns(struct kobject *kobj, const struct ns_common *ns)
|
||||
{
|
||||
struct kernfs_node *parent, *kn;
|
||||
kuid_t uid;
|
||||
@@ -103,7 +103,7 @@ void sysfs_remove_dir(struct kobject *kobj)
|
||||
}
|
||||
|
||||
int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
|
||||
const void *new_ns)
|
||||
const struct ns_common *new_ns)
|
||||
{
|
||||
struct kernfs_node *parent;
|
||||
int ret;
|
||||
@@ -115,7 +115,7 @@ int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
|
||||
}
|
||||
|
||||
int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
|
||||
const void *new_ns)
|
||||
const struct ns_common *new_ns)
|
||||
{
|
||||
struct kernfs_node *kn = kobj->sd;
|
||||
struct kernfs_node *new_parent;
|
||||
|
||||
+4
-4
@@ -272,7 +272,7 @@ static const struct kernfs_ops sysfs_bin_kfops_mmap = {
|
||||
|
||||
int sysfs_add_file_mode_ns(struct kernfs_node *parent,
|
||||
const struct attribute *attr, umode_t mode, kuid_t uid,
|
||||
kgid_t gid, const void *ns)
|
||||
kgid_t gid, const struct ns_common *ns)
|
||||
{
|
||||
struct kobject *kobj = parent->priv;
|
||||
const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops;
|
||||
@@ -322,7 +322,7 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
|
||||
|
||||
int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
|
||||
const struct bin_attribute *battr, umode_t mode, size_t size,
|
||||
kuid_t uid, kgid_t gid, const void *ns)
|
||||
kuid_t uid, kgid_t gid, const struct ns_common *ns)
|
||||
{
|
||||
const struct attribute *attr = &battr->attr;
|
||||
struct lock_class_key *key = NULL;
|
||||
@@ -362,7 +362,7 @@ int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
|
||||
* @ns: namespace the new file should belong to
|
||||
*/
|
||||
int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
kuid_t uid;
|
||||
kgid_t gid;
|
||||
@@ -505,7 +505,7 @@ EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection);
|
||||
* Hash the attribute name and namespace tag and kill the victim.
|
||||
*/
|
||||
void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
struct kernfs_node *parent = kobj->sd;
|
||||
|
||||
|
||||
+6
-4
@@ -55,7 +55,7 @@ static const struct fs_context_operations sysfs_fs_context_ops = {
|
||||
static int sysfs_init_fs_context(struct fs_context *fc)
|
||||
{
|
||||
struct kernfs_fs_context *kfc;
|
||||
struct net *netns;
|
||||
struct ns_common *ns;
|
||||
|
||||
if (!(fc->sb_flags & SB_KERNMOUNT)) {
|
||||
if (!kobj_ns_current_may_mount(KOBJ_NS_TYPE_NET))
|
||||
@@ -66,12 +66,14 @@ static int sysfs_init_fs_context(struct fs_context *fc)
|
||||
if (!kfc)
|
||||
return -ENOMEM;
|
||||
|
||||
kfc->ns_tag = netns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
|
||||
kfc->ns_tag = ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
|
||||
kfc->root = sysfs_root;
|
||||
kfc->magic = SYSFS_MAGIC;
|
||||
fc->fs_private = kfc;
|
||||
fc->ops = &sysfs_fs_context_ops;
|
||||
if (netns) {
|
||||
if (ns) {
|
||||
struct net *netns = to_net_ns(ns);
|
||||
|
||||
put_user_ns(fc->user_ns);
|
||||
fc->user_ns = get_user_ns(netns->user_ns);
|
||||
}
|
||||
@@ -81,7 +83,7 @@ static int sysfs_init_fs_context(struct fs_context *fc)
|
||||
|
||||
static void sysfs_kill_sb(struct super_block *sb)
|
||||
{
|
||||
void *ns = (void *)kernfs_super_ns(sb);
|
||||
struct ns_common *ns = (struct ns_common *)kernfs_super_ns(sb);
|
||||
|
||||
kernfs_kill_sb(sb);
|
||||
kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
|
||||
|
||||
+4
-3
@@ -121,7 +121,7 @@ EXPORT_SYMBOL_GPL(sysfs_create_link_nowarn);
|
||||
void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
|
||||
const char *name)
|
||||
{
|
||||
const void *ns = NULL;
|
||||
const struct ns_common *ns = NULL;
|
||||
|
||||
/*
|
||||
* We don't own @target and it may be removed at any time.
|
||||
@@ -164,10 +164,11 @@ EXPORT_SYMBOL_GPL(sysfs_remove_link);
|
||||
* A helper function for the common rename symlink idiom.
|
||||
*/
|
||||
int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
|
||||
const char *old, const char *new, const void *new_ns)
|
||||
const char *old, const char *new,
|
||||
const struct ns_common *new_ns)
|
||||
{
|
||||
struct kernfs_node *parent, *kn = NULL;
|
||||
const void *old_ns = NULL;
|
||||
const struct ns_common *old_ns = NULL;
|
||||
int result;
|
||||
|
||||
if (!kobj)
|
||||
|
||||
+2
-2
@@ -29,10 +29,10 @@ void sysfs_warn_dup(struct kernfs_node *parent, const char *name);
|
||||
*/
|
||||
int sysfs_add_file_mode_ns(struct kernfs_node *parent,
|
||||
const struct attribute *attr, umode_t amode, kuid_t uid,
|
||||
kgid_t gid, const void *ns);
|
||||
kgid_t gid, const struct ns_common *ns);
|
||||
int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
|
||||
const struct bin_attribute *battr, umode_t mode, size_t size,
|
||||
kuid_t uid, kgid_t gid, const void *ns);
|
||||
kuid_t uid, kgid_t gid, const struct ns_common *ns);
|
||||
|
||||
/*
|
||||
* symlink.c
|
||||
|
||||
+3
-3
@@ -229,8 +229,8 @@ static inline bool cpu_attack_vector_mitigated(enum cpu_attack_vectors v)
|
||||
#define smt_mitigations SMT_MITIGATIONS_OFF
|
||||
#endif
|
||||
|
||||
int arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status);
|
||||
int arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status);
|
||||
int arch_lock_indir_br_lp_status(struct task_struct *t, unsigned long status);
|
||||
int arch_prctl_get_branch_landing_pad_state(struct task_struct *t, unsigned long __user *state);
|
||||
int arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long state);
|
||||
int arch_prctl_lock_branch_landing_pad_state(struct task_struct *t);
|
||||
|
||||
#endif /* _LINUX_CPU_H_ */
|
||||
@@ -62,7 +62,7 @@ struct class {
|
||||
int (*shutdown_pre)(struct device *dev);
|
||||
|
||||
const struct kobj_ns_type_operations *ns_type;
|
||||
const void *(*namespace)(const struct device *dev);
|
||||
const struct ns_common *(*namespace)(const struct device *dev);
|
||||
|
||||
void (*get_ownership)(const struct device *dev, kuid_t *uid, kgid_t *gid);
|
||||
|
||||
@@ -180,9 +180,9 @@ struct class_attribute {
|
||||
struct class_attribute class_attr_##_name = __ATTR_WO(_name)
|
||||
|
||||
int __must_check class_create_file_ns(const struct class *class, const struct class_attribute *attr,
|
||||
const void *ns);
|
||||
const struct ns_common *ns);
|
||||
void class_remove_file_ns(const struct class *class, const struct class_attribute *attr,
|
||||
const void *ns);
|
||||
const struct ns_common *ns);
|
||||
|
||||
static inline int __must_check class_create_file(const struct class *class,
|
||||
const struct class_attribute *attr)
|
||||
|
||||
+24
-16
@@ -23,6 +23,7 @@
|
||||
struct file;
|
||||
struct dentry;
|
||||
struct iattr;
|
||||
struct ns_common;
|
||||
struct seq_file;
|
||||
struct vm_area_struct;
|
||||
struct vm_operations_struct;
|
||||
@@ -209,7 +210,7 @@ struct kernfs_node {
|
||||
|
||||
struct rb_node rb;
|
||||
|
||||
const void *ns; /* namespace tag */
|
||||
const struct ns_common *ns; /* namespace tag */
|
||||
unsigned int hash; /* ns + name hash */
|
||||
unsigned short flags;
|
||||
umode_t mode;
|
||||
@@ -331,7 +332,7 @@ struct kernfs_ops {
|
||||
*/
|
||||
struct kernfs_fs_context {
|
||||
struct kernfs_root *root; /* Root of the hierarchy being mounted */
|
||||
void *ns_tag; /* Namespace tag of the mount (or NULL) */
|
||||
struct ns_common *ns_tag; /* Namespace tag of the mount (or NULL) */
|
||||
unsigned long magic; /* File system specific magic number */
|
||||
|
||||
/* The following are set/used by kernfs_mount() */
|
||||
@@ -406,9 +407,11 @@ void pr_cont_kernfs_name(struct kernfs_node *kn);
|
||||
void pr_cont_kernfs_path(struct kernfs_node *kn);
|
||||
struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn);
|
||||
struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent,
|
||||
const char *name, const void *ns);
|
||||
const char *name,
|
||||
const struct ns_common *ns);
|
||||
struct kernfs_node *kernfs_walk_and_get_ns(struct kernfs_node *parent,
|
||||
const char *path, const void *ns);
|
||||
const char *path,
|
||||
const struct ns_common *ns);
|
||||
void kernfs_get(struct kernfs_node *kn);
|
||||
void kernfs_put(struct kernfs_node *kn);
|
||||
|
||||
@@ -426,7 +429,8 @@ unsigned int kernfs_root_flags(struct kernfs_node *kn);
|
||||
struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
|
||||
const char *name, umode_t mode,
|
||||
kuid_t uid, kgid_t gid,
|
||||
void *priv, const void *ns);
|
||||
void *priv,
|
||||
const struct ns_common *ns);
|
||||
struct kernfs_node *kernfs_create_empty_dir(struct kernfs_node *parent,
|
||||
const char *name);
|
||||
struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
|
||||
@@ -434,7 +438,8 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
|
||||
kuid_t uid, kgid_t gid,
|
||||
loff_t size,
|
||||
const struct kernfs_ops *ops,
|
||||
void *priv, const void *ns,
|
||||
void *priv,
|
||||
const struct ns_common *ns,
|
||||
struct lock_class_key *key);
|
||||
struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
|
||||
const char *name,
|
||||
@@ -446,9 +451,9 @@ void kernfs_break_active_protection(struct kernfs_node *kn);
|
||||
void kernfs_unbreak_active_protection(struct kernfs_node *kn);
|
||||
bool kernfs_remove_self(struct kernfs_node *kn);
|
||||
int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name,
|
||||
const void *ns);
|
||||
const struct ns_common *ns);
|
||||
int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
|
||||
const char *new_name, const void *new_ns);
|
||||
const char *new_name, const struct ns_common *new_ns);
|
||||
int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr);
|
||||
__poll_t kernfs_generic_poll(struct kernfs_open_file *of,
|
||||
struct poll_table_struct *pt);
|
||||
@@ -459,7 +464,7 @@ int kernfs_xattr_get(struct kernfs_node *kn, const char *name,
|
||||
int kernfs_xattr_set(struct kernfs_node *kn, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
|
||||
const void *kernfs_super_ns(struct super_block *sb);
|
||||
const struct ns_common *kernfs_super_ns(struct super_block *sb);
|
||||
int kernfs_get_tree(struct fs_context *fc);
|
||||
void kernfs_free_fs_context(struct fs_context *fc);
|
||||
void kernfs_kill_sb(struct super_block *sb);
|
||||
@@ -494,11 +499,11 @@ static inline struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
|
||||
|
||||
static inline struct kernfs_node *
|
||||
kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{ return NULL; }
|
||||
static inline struct kernfs_node *
|
||||
kernfs_walk_and_get_ns(struct kernfs_node *parent, const char *path,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{ return NULL; }
|
||||
|
||||
static inline void kernfs_get(struct kernfs_node *kn) { }
|
||||
@@ -526,14 +531,15 @@ static inline unsigned int kernfs_root_flags(struct kernfs_node *kn)
|
||||
static inline struct kernfs_node *
|
||||
kernfs_create_dir_ns(struct kernfs_node *parent, const char *name,
|
||||
umode_t mode, kuid_t uid, kgid_t gid,
|
||||
void *priv, const void *ns)
|
||||
void *priv, const struct ns_common *ns)
|
||||
{ return ERR_PTR(-ENOSYS); }
|
||||
|
||||
static inline struct kernfs_node *
|
||||
__kernfs_create_file(struct kernfs_node *parent, const char *name,
|
||||
umode_t mode, kuid_t uid, kgid_t gid,
|
||||
loff_t size, const struct kernfs_ops *ops,
|
||||
void *priv, const void *ns, struct lock_class_key *key)
|
||||
void *priv, const struct ns_common *ns,
|
||||
struct lock_class_key *key)
|
||||
{ return ERR_PTR(-ENOSYS); }
|
||||
|
||||
static inline struct kernfs_node *
|
||||
@@ -549,12 +555,14 @@ static inline bool kernfs_remove_self(struct kernfs_node *kn)
|
||||
{ return false; }
|
||||
|
||||
static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn,
|
||||
const char *name, const void *ns)
|
||||
const char *name,
|
||||
const struct ns_common *ns)
|
||||
{ return -ENOSYS; }
|
||||
|
||||
static inline int kernfs_rename_ns(struct kernfs_node *kn,
|
||||
struct kernfs_node *new_parent,
|
||||
const char *new_name, const void *new_ns)
|
||||
const char *new_name,
|
||||
const struct ns_common *new_ns)
|
||||
{ return -ENOSYS; }
|
||||
|
||||
static inline int kernfs_setattr(struct kernfs_node *kn,
|
||||
@@ -575,7 +583,7 @@ static inline int kernfs_xattr_set(struct kernfs_node *kn, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{ return -ENOSYS; }
|
||||
|
||||
static inline const void *kernfs_super_ns(struct super_block *sb)
|
||||
static inline const struct ns_common *kernfs_super_ns(struct super_block *sb)
|
||||
{ return NULL; }
|
||||
|
||||
static inline int kernfs_get_tree(struct fs_context *fc)
|
||||
|
||||
@@ -109,7 +109,7 @@ struct kobject *kobject_get(struct kobject *kobj);
|
||||
struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj);
|
||||
void kobject_put(struct kobject *kobj);
|
||||
|
||||
const void *kobject_namespace(const struct kobject *kobj);
|
||||
const struct ns_common *kobject_namespace(const struct kobject *kobj);
|
||||
void kobject_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid);
|
||||
char *kobject_get_path(const struct kobject *kobj, gfp_t flag);
|
||||
|
||||
@@ -118,7 +118,7 @@ struct kobj_type {
|
||||
const struct sysfs_ops *sysfs_ops;
|
||||
const struct attribute_group **default_groups;
|
||||
const struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);
|
||||
const void *(*namespace)(const struct kobject *kobj);
|
||||
const struct ns_common *(*namespace)(const struct kobject *kobj);
|
||||
void (*get_ownership)(const struct kobject *kobj, kuid_t *uid, kgid_t *gid);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#ifndef _LINUX_KOBJECT_NS_H
|
||||
#define _LINUX_KOBJECT_NS_H
|
||||
|
||||
struct ns_common;
|
||||
struct sock;
|
||||
struct kobject;
|
||||
|
||||
@@ -39,10 +40,10 @@ enum kobj_ns_type {
|
||||
struct kobj_ns_type_operations {
|
||||
enum kobj_ns_type type;
|
||||
bool (*current_may_mount)(void);
|
||||
void *(*grab_current_ns)(void);
|
||||
const void *(*netlink_ns)(struct sock *sk);
|
||||
const void *(*initial_ns)(void);
|
||||
void (*drop_ns)(void *);
|
||||
struct ns_common *(*grab_current_ns)(void);
|
||||
const struct ns_common *(*netlink_ns)(struct sock *sk);
|
||||
const struct ns_common *(*initial_ns)(void);
|
||||
void (*drop_ns)(struct ns_common *);
|
||||
};
|
||||
|
||||
int kobj_ns_type_register(const struct kobj_ns_type_operations *ops);
|
||||
@@ -51,7 +52,7 @@ const struct kobj_ns_type_operations *kobj_child_ns_ops(const struct kobject *pa
|
||||
const struct kobj_ns_type_operations *kobj_ns_ops(const struct kobject *kobj);
|
||||
|
||||
bool kobj_ns_current_may_mount(enum kobj_ns_type type);
|
||||
void *kobj_ns_grab_current(enum kobj_ns_type type);
|
||||
void kobj_ns_drop(enum kobj_ns_type type, void *ns);
|
||||
struct ns_common *kobj_ns_grab_current(enum kobj_ns_type type);
|
||||
void kobj_ns_drop(enum kobj_ns_type type, struct ns_common *ns);
|
||||
|
||||
#endif /* _LINUX_KOBJECT_NS_H */
|
||||
@@ -5338,9 +5338,9 @@ static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_devi
|
||||
}
|
||||
|
||||
int netdev_class_create_file_ns(const struct class_attribute *class_attr,
|
||||
const void *ns);
|
||||
const struct ns_common *ns);
|
||||
void netdev_class_remove_file_ns(const struct class_attribute *class_attr,
|
||||
const void *ns);
|
||||
const struct ns_common *ns);
|
||||
|
||||
extern const struct kobj_ns_type_operations net_ns_type_operations;
|
||||
|
||||
|
||||
+12
-12
@@ -396,13 +396,13 @@ struct sysfs_ops {
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns);
|
||||
int __must_check sysfs_create_dir_ns(struct kobject *kobj, const struct ns_common *ns);
|
||||
void sysfs_remove_dir(struct kobject *kobj);
|
||||
int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
|
||||
const void *new_ns);
|
||||
const struct ns_common *new_ns);
|
||||
int __must_check sysfs_move_dir_ns(struct kobject *kobj,
|
||||
struct kobject *new_parent_kobj,
|
||||
const void *new_ns);
|
||||
const struct ns_common *new_ns);
|
||||
int __must_check sysfs_create_mount_point(struct kobject *parent_kobj,
|
||||
const char *name);
|
||||
void sysfs_remove_mount_point(struct kobject *parent_kobj,
|
||||
@@ -410,7 +410,7 @@ void sysfs_remove_mount_point(struct kobject *parent_kobj,
|
||||
|
||||
int __must_check sysfs_create_file_ns(struct kobject *kobj,
|
||||
const struct attribute *attr,
|
||||
const void *ns);
|
||||
const struct ns_common *ns);
|
||||
int __must_check sysfs_create_files(struct kobject *kobj,
|
||||
const struct attribute * const *attr);
|
||||
int __must_check sysfs_chmod_file(struct kobject *kobj,
|
||||
@@ -419,7 +419,7 @@ struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
|
||||
const struct attribute *attr);
|
||||
void sysfs_unbreak_active_protection(struct kernfs_node *kn);
|
||||
void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
|
||||
const void *ns);
|
||||
const struct ns_common *ns);
|
||||
bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr);
|
||||
void sysfs_remove_files(struct kobject *kobj, const struct attribute * const *attr);
|
||||
|
||||
@@ -437,7 +437,7 @@ void sysfs_remove_link(struct kobject *kobj, const char *name);
|
||||
|
||||
int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *target,
|
||||
const char *old_name, const char *new_name,
|
||||
const void *new_ns);
|
||||
const struct ns_common *new_ns);
|
||||
|
||||
void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
|
||||
const char *name);
|
||||
@@ -502,7 +502,7 @@ ssize_t sysfs_bin_attr_simple_read(struct file *file, struct kobject *kobj,
|
||||
|
||||
#else /* CONFIG_SYSFS */
|
||||
|
||||
static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
|
||||
static inline int sysfs_create_dir_ns(struct kobject *kobj, const struct ns_common *ns)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -512,14 +512,14 @@ static inline void sysfs_remove_dir(struct kobject *kobj)
|
||||
}
|
||||
|
||||
static inline int sysfs_rename_dir_ns(struct kobject *kobj,
|
||||
const char *new_name, const void *new_ns)
|
||||
const char *new_name, const struct ns_common *new_ns)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sysfs_move_dir_ns(struct kobject *kobj,
|
||||
struct kobject *new_parent_kobj,
|
||||
const void *new_ns)
|
||||
const struct ns_common *new_ns)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -537,7 +537,7 @@ static inline void sysfs_remove_mount_point(struct kobject *parent_kobj,
|
||||
|
||||
static inline int sysfs_create_file_ns(struct kobject *kobj,
|
||||
const struct attribute *attr,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -567,7 +567,7 @@ static inline void sysfs_unbreak_active_protection(struct kernfs_node *kn)
|
||||
|
||||
static inline void sysfs_remove_file_ns(struct kobject *kobj,
|
||||
const struct attribute *attr,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -612,7 +612,7 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
|
||||
|
||||
static inline int sysfs_rename_link_ns(struct kobject *k, struct kobject *t,
|
||||
const char *old_name,
|
||||
const char *new_name, const void *ns)
|
||||
const char *new_name, const struct ns_common *ns)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -264,14 +264,14 @@ void ipx_unregister_sysctl(void);
|
||||
#define ipx_unregister_sysctl()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_NS
|
||||
void __put_net(struct net *net);
|
||||
|
||||
static inline struct net *to_net_ns(struct ns_common *ns)
|
||||
{
|
||||
return container_of(ns, struct net, ns);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_NS
|
||||
void __put_net(struct net *net);
|
||||
|
||||
/* Try using get_net_track() instead */
|
||||
static inline struct net *get_net(struct net *net)
|
||||
{
|
||||
@@ -309,7 +309,7 @@ static inline int check_net(const struct net *net)
|
||||
return ns_ref_read(net) != 0;
|
||||
}
|
||||
|
||||
void net_drop_ns(void *);
|
||||
void net_drop_ns(struct ns_common *);
|
||||
void net_passive_dec(struct net *net);
|
||||
|
||||
#else
|
||||
|
||||
@@ -69,6 +69,8 @@ struct sdca_interrupt_info {
|
||||
int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *interrupt_info,
|
||||
int sdca_irq, const char *name, irq_handler_t handler,
|
||||
void *data);
|
||||
void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *interrupt_info,
|
||||
int sdca_irq, const char *name, void *data);
|
||||
int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap,
|
||||
struct snd_soc_component *component,
|
||||
struct sdca_function_data *function,
|
||||
@@ -81,6 +83,9 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *function_regmap,
|
||||
int sdca_irq_populate(struct sdca_function_data *function,
|
||||
struct snd_soc_component *component,
|
||||
struct sdca_interrupt_info *info);
|
||||
void sdca_irq_cleanup(struct device *dev,
|
||||
struct sdca_function_data *function,
|
||||
struct sdca_interrupt_info *info);
|
||||
struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev,
|
||||
struct regmap *regmap, int irq);
|
||||
|
||||
|
||||
+15
-22
@@ -397,30 +397,23 @@ struct prctl_mm_map {
|
||||
# define PR_RSEQ_SLICE_EXT_ENABLE 0x01
|
||||
|
||||
/*
|
||||
* Get the current indirect branch tracking configuration for the current
|
||||
* thread, this will be the value configured via PR_SET_INDIR_BR_LP_STATUS.
|
||||
* Get or set the control flow integrity (CFI) configuration for the
|
||||
* current thread.
|
||||
*
|
||||
* Some per-thread control flow integrity settings are not yet
|
||||
* controlled through this prctl(); see for example
|
||||
* PR_{GET,SET,LOCK}_SHADOW_STACK_STATUS
|
||||
*/
|
||||
#define PR_GET_INDIR_BR_LP_STATUS 80
|
||||
|
||||
#define PR_GET_CFI 80
|
||||
#define PR_SET_CFI 81
|
||||
/*
|
||||
* Set the indirect branch tracking configuration. PR_INDIR_BR_LP_ENABLE will
|
||||
* enable cpu feature for user thread, to track all indirect branches and ensure
|
||||
* they land on arch defined landing pad instruction.
|
||||
* x86 - If enabled, an indirect branch must land on an ENDBRANCH instruction.
|
||||
* arch64 - If enabled, an indirect branch must land on a BTI instruction.
|
||||
* riscv - If enabled, an indirect branch must land on an lpad instruction.
|
||||
* PR_INDIR_BR_LP_DISABLE will disable feature for user thread and indirect
|
||||
* branches will no more be tracked by cpu to land on arch defined landing pad
|
||||
* instruction.
|
||||
* Forward-edge CFI variants (excluding ARM64 BTI, which has its own
|
||||
* prctl()s).
|
||||
*/
|
||||
#define PR_SET_INDIR_BR_LP_STATUS 81
|
||||
# define PR_INDIR_BR_LP_ENABLE (1UL << 0)
|
||||
|
||||
/*
|
||||
* Prevent further changes to the specified indirect branch tracking
|
||||
* configuration. All bits may be locked via this call, including
|
||||
* undefined bits.
|
||||
*/
|
||||
#define PR_LOCK_INDIR_BR_LP_STATUS 82
|
||||
#define PR_CFI_BRANCH_LANDING_PADS 0
|
||||
/* Return and control values for PR_{GET,SET}_CFI */
|
||||
# define PR_CFI_ENABLE _BITUL(0)
|
||||
# define PR_CFI_DISABLE _BITUL(1)
|
||||
# define PR_CFI_LOCK _BITUL(2)
|
||||
|
||||
#endif /* _LINUX_PRCTL_H */
|
||||
+17
-13
@@ -2390,17 +2390,18 @@ int __weak arch_lock_shadow_stack_status(struct task_struct *t, unsigned long st
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int __weak arch_get_indir_br_lp_status(struct task_struct *t, unsigned long __user *status)
|
||||
int __weak arch_prctl_get_branch_landing_pad_state(struct task_struct *t,
|
||||
unsigned long __user *state)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int __weak arch_set_indir_br_lp_status(struct task_struct *t, unsigned long status)
|
||||
int __weak arch_prctl_set_branch_landing_pad_state(struct task_struct *t, unsigned long state)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int __weak arch_lock_indir_br_lp_status(struct task_struct *t, unsigned long status)
|
||||
int __weak arch_prctl_lock_branch_landing_pad_state(struct task_struct *t)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2890,20 +2891,23 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
|
||||
return -EINVAL;
|
||||
error = rseq_slice_extension_prctl(arg2, arg3);
|
||||
break;
|
||||
case PR_GET_INDIR_BR_LP_STATUS:
|
||||
if (arg3 || arg4 || arg5)
|
||||
case PR_GET_CFI:
|
||||
if (arg2 != PR_CFI_BRANCH_LANDING_PADS)
|
||||
return -EINVAL;
|
||||
error = arch_get_indir_br_lp_status(me, (unsigned long __user *)arg2);
|
||||
if (arg4 || arg5)
|
||||
return -EINVAL;
|
||||
error = arch_prctl_get_branch_landing_pad_state(me, (unsigned long __user *)arg3);
|
||||
break;
|
||||
case PR_SET_INDIR_BR_LP_STATUS:
|
||||
if (arg3 || arg4 || arg5)
|
||||
case PR_SET_CFI:
|
||||
if (arg2 != PR_CFI_BRANCH_LANDING_PADS)
|
||||
return -EINVAL;
|
||||
error = arch_set_indir_br_lp_status(me, arg2);
|
||||
break;
|
||||
case PR_LOCK_INDIR_BR_LP_STATUS:
|
||||
if (arg3 || arg4 || arg5)
|
||||
if (arg4 || arg5)
|
||||
return -EINVAL;
|
||||
error = arch_lock_indir_br_lp_status(me, arg2);
|
||||
error = arch_prctl_set_branch_landing_pad_state(me, arg3);
|
||||
if (error)
|
||||
break;
|
||||
if (arg3 & PR_CFI_LOCK && !(arg3 & PR_CFI_DISABLE))
|
||||
error = arch_prctl_lock_branch_landing_pad_state(me);
|
||||
break;
|
||||
default:
|
||||
trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5);
|
||||
|
||||
+4
-4
@@ -27,7 +27,7 @@
|
||||
* and thus @kobj should have a namespace tag associated with it. Returns
|
||||
* %NULL otherwise.
|
||||
*/
|
||||
const void *kobject_namespace(const struct kobject *kobj)
|
||||
const struct ns_common *kobject_namespace(const struct kobject *kobj)
|
||||
{
|
||||
const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj);
|
||||
|
||||
@@ -1083,9 +1083,9 @@ bool kobj_ns_current_may_mount(enum kobj_ns_type type)
|
||||
return may_mount;
|
||||
}
|
||||
|
||||
void *kobj_ns_grab_current(enum kobj_ns_type type)
|
||||
struct ns_common *kobj_ns_grab_current(enum kobj_ns_type type)
|
||||
{
|
||||
void *ns = NULL;
|
||||
struct ns_common *ns = NULL;
|
||||
|
||||
spin_lock(&kobj_ns_type_lock);
|
||||
if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
|
||||
@@ -1096,7 +1096,7 @@ void *kobj_ns_grab_current(enum kobj_ns_type type)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kobj_ns_grab_current);
|
||||
|
||||
void kobj_ns_drop(enum kobj_ns_type type, void *ns)
|
||||
void kobj_ns_drop(enum kobj_ns_type type, struct ns_common *ns)
|
||||
{
|
||||
spin_lock(&kobj_ns_type_lock);
|
||||
if (kobj_ns_type_is_valid(type) &&
|
||||
|
||||
@@ -238,7 +238,7 @@ static int kobj_usermode_filter(struct kobject *kobj)
|
||||
|
||||
ops = kobj_ns_ops(kobj);
|
||||
if (ops) {
|
||||
const void *init_ns, *ns;
|
||||
const struct ns_common *init_ns, *ns;
|
||||
|
||||
ns = kobj->ktype->namespace(kobj);
|
||||
init_ns = ops->initial_ns();
|
||||
@@ -388,7 +388,7 @@ static int kobject_uevent_net_broadcast(struct kobject *kobj,
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
const struct kobj_ns_type_operations *ops;
|
||||
const struct net *net = NULL;
|
||||
const struct ns_common *ns = NULL;
|
||||
|
||||
ops = kobj_ns_ops(kobj);
|
||||
if (!ops && kobj->kset) {
|
||||
@@ -404,14 +404,17 @@ static int kobject_uevent_net_broadcast(struct kobject *kobj,
|
||||
*/
|
||||
if (ops && ops->netlink_ns && kobj->ktype->namespace)
|
||||
if (ops->type == KOBJ_NS_TYPE_NET)
|
||||
net = kobj->ktype->namespace(kobj);
|
||||
ns = kobj->ktype->namespace(kobj);
|
||||
|
||||
if (!net)
|
||||
if (!ns)
|
||||
ret = uevent_net_broadcast_untagged(env, action_string,
|
||||
devpath);
|
||||
else
|
||||
else {
|
||||
const struct net *net = container_of(ns, struct net, ns);
|
||||
|
||||
ret = uevent_net_broadcast_tagged(net->uevent_sock->sk, env,
|
||||
action_string, devpath);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
||||
+25
-25
@@ -1177,24 +1177,24 @@ static void rx_queue_release(struct kobject *kobj)
|
||||
netdev_put(queue->dev, &queue->dev_tracker);
|
||||
}
|
||||
|
||||
static const void *rx_queue_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *rx_queue_namespace(const struct kobject *kobj)
|
||||
{
|
||||
struct netdev_rx_queue *queue = to_rx_queue(kobj);
|
||||
struct device *dev = &queue->dev->dev;
|
||||
const void *ns = NULL;
|
||||
|
||||
if (dev->class && dev->class->namespace)
|
||||
ns = dev->class->namespace(dev);
|
||||
return dev->class->namespace(dev);
|
||||
|
||||
return ns;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void rx_queue_get_ownership(const struct kobject *kobj,
|
||||
kuid_t *uid, kgid_t *gid)
|
||||
{
|
||||
const struct net *net = rx_queue_namespace(kobj);
|
||||
const struct ns_common *ns = rx_queue_namespace(kobj);
|
||||
|
||||
net_ns_get_ownership(net, uid, gid);
|
||||
net_ns_get_ownership(ns ? container_of(ns, struct net, ns) : NULL,
|
||||
uid, gid);
|
||||
}
|
||||
|
||||
static const struct kobj_type rx_queue_ktype = {
|
||||
@@ -1927,24 +1927,24 @@ static void netdev_queue_release(struct kobject *kobj)
|
||||
netdev_put(queue->dev, &queue->dev_tracker);
|
||||
}
|
||||
|
||||
static const void *netdev_queue_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *netdev_queue_namespace(const struct kobject *kobj)
|
||||
{
|
||||
struct netdev_queue *queue = to_netdev_queue(kobj);
|
||||
struct device *dev = &queue->dev->dev;
|
||||
const void *ns = NULL;
|
||||
|
||||
if (dev->class && dev->class->namespace)
|
||||
ns = dev->class->namespace(dev);
|
||||
return dev->class->namespace(dev);
|
||||
|
||||
return ns;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void netdev_queue_get_ownership(const struct kobject *kobj,
|
||||
kuid_t *uid, kgid_t *gid)
|
||||
{
|
||||
const struct net *net = netdev_queue_namespace(kobj);
|
||||
const struct ns_common *ns = netdev_queue_namespace(kobj);
|
||||
|
||||
net_ns_get_ownership(net, uid, gid);
|
||||
net_ns_get_ownership(ns ? container_of(ns, struct net, ns) : NULL,
|
||||
uid, gid);
|
||||
}
|
||||
|
||||
static const struct kobj_type netdev_queue_ktype = {
|
||||
@@ -2181,24 +2181,24 @@ static bool net_current_may_mount(void)
|
||||
return ns_capable(net->user_ns, CAP_SYS_ADMIN);
|
||||
}
|
||||
|
||||
static void *net_grab_current_ns(void)
|
||||
static struct ns_common *net_grab_current_ns(void)
|
||||
{
|
||||
struct net *ns = current->nsproxy->net_ns;
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
#ifdef CONFIG_NET_NS
|
||||
if (ns)
|
||||
refcount_inc(&ns->passive);
|
||||
if (net)
|
||||
refcount_inc(&net->passive);
|
||||
#endif
|
||||
return ns;
|
||||
return net ? to_ns_common(net) : NULL;
|
||||
}
|
||||
|
||||
static const void *net_initial_ns(void)
|
||||
static const struct ns_common *net_initial_ns(void)
|
||||
{
|
||||
return &init_net;
|
||||
return to_ns_common(&init_net);
|
||||
}
|
||||
|
||||
static const void *net_netlink_ns(struct sock *sk)
|
||||
static const struct ns_common *net_netlink_ns(struct sock *sk)
|
||||
{
|
||||
return sock_net(sk);
|
||||
return to_ns_common(sock_net(sk));
|
||||
}
|
||||
|
||||
const struct kobj_ns_type_operations net_ns_type_operations = {
|
||||
@@ -2248,11 +2248,11 @@ static void netdev_release(struct device *d)
|
||||
kvfree(dev);
|
||||
}
|
||||
|
||||
static const void *net_namespace(const struct device *d)
|
||||
static const struct ns_common *net_namespace(const struct device *d)
|
||||
{
|
||||
const struct net_device *dev = to_net_dev(d);
|
||||
|
||||
return dev_net(dev);
|
||||
return to_ns_common(dev_net(dev));
|
||||
}
|
||||
|
||||
static void net_get_ownership(const struct device *d, kuid_t *uid, kgid_t *gid)
|
||||
@@ -2398,14 +2398,14 @@ int netdev_change_owner(struct net_device *ndev, const struct net *net_old,
|
||||
}
|
||||
|
||||
int netdev_class_create_file_ns(const struct class_attribute *class_attr,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
return class_create_file_ns(&net_class, class_attr, ns);
|
||||
}
|
||||
EXPORT_SYMBOL(netdev_class_create_file_ns);
|
||||
|
||||
void netdev_class_remove_file_ns(const struct class_attribute *class_attr,
|
||||
const void *ns)
|
||||
const struct ns_common *ns)
|
||||
{
|
||||
class_remove_file_ns(&net_class, class_attr, ns);
|
||||
}
|
||||
|
||||
@@ -540,12 +540,10 @@ void net_passive_dec(struct net *net)
|
||||
}
|
||||
}
|
||||
|
||||
void net_drop_ns(void *p)
|
||||
void net_drop_ns(struct ns_common *ns)
|
||||
{
|
||||
struct net *net = (struct net *)p;
|
||||
|
||||
if (net)
|
||||
net_passive_dec(net);
|
||||
if (ns)
|
||||
net_passive_dec(to_net_ns(ns));
|
||||
}
|
||||
|
||||
struct net *copy_net_ns(u64 flags,
|
||||
|
||||
+10
-7
@@ -6,6 +6,7 @@
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/sunrpc/addr.h>
|
||||
#include <linux/sunrpc/xprtsock.h>
|
||||
#include <net/net_namespace.h>
|
||||
|
||||
#include "sysfs.h"
|
||||
|
||||
@@ -553,20 +554,22 @@ static void rpc_sysfs_xprt_release(struct kobject *kobj)
|
||||
kfree(xprt);
|
||||
}
|
||||
|
||||
static const void *rpc_sysfs_client_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *rpc_sysfs_client_namespace(const struct kobject *kobj)
|
||||
{
|
||||
return container_of(kobj, struct rpc_sysfs_client, kobject)->net;
|
||||
return to_ns_common(container_of(kobj, struct rpc_sysfs_client,
|
||||
kobject)->net);
|
||||
}
|
||||
|
||||
static const void *rpc_sysfs_xprt_switch_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *rpc_sysfs_xprt_switch_namespace(const struct kobject *kobj)
|
||||
{
|
||||
return container_of(kobj, struct rpc_sysfs_xprt_switch, kobject)->net;
|
||||
return to_ns_common(container_of(kobj, struct rpc_sysfs_xprt_switch,
|
||||
kobject)->net);
|
||||
}
|
||||
|
||||
static const void *rpc_sysfs_xprt_namespace(const struct kobject *kobj)
|
||||
static const struct ns_common *rpc_sysfs_xprt_namespace(const struct kobject *kobj)
|
||||
{
|
||||
return container_of(kobj, struct rpc_sysfs_xprt,
|
||||
kobject)->xprt->xprt_net;
|
||||
return to_ns_common(container_of(kobj, struct rpc_sysfs_xprt,
|
||||
kobject)->xprt->xprt_net);
|
||||
}
|
||||
|
||||
static struct kobj_attribute rpc_sysfs_clnt_version = __ATTR(rpc_version,
|
||||
|
||||
@@ -154,11 +154,11 @@ static SIMPLE_DEV_PM_OPS(wiphy_pm_ops, wiphy_suspend, wiphy_resume);
|
||||
#define WIPHY_PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static const void *wiphy_namespace(const struct device *d)
|
||||
static const struct ns_common *wiphy_namespace(const struct device *d)
|
||||
{
|
||||
struct wiphy *wiphy = container_of(d, struct wiphy, dev);
|
||||
|
||||
return wiphy_net(wiphy);
|
||||
return to_ns_common(wiphy_net(wiphy));
|
||||
}
|
||||
|
||||
struct class ieee80211_class = {
|
||||
|
||||
@@ -195,7 +195,7 @@ tar%-pkg: linux-$(KERNELRELEASE)-$(ARCH).tar.% FORCE
|
||||
.tmp_modules_cpio: FORCE
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile
|
||||
$(Q)rm -rf $@
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile INSTALL_MOD_PATH=$@ modules_install
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile INSTALL_MOD_PATH=$@/$(INSTALL_MOD_PATH) modules_install
|
||||
|
||||
quiet_cmd_cpio = CPIO $@
|
||||
cmd_cpio = $(CONFIG_SHELL) $(srctree)/usr/gen_initramfs.sh -o $@ $<
|
||||
@@ -264,6 +264,7 @@ help:
|
||||
@echo ' tarxz-pkg - Build the kernel as a xz compressed tarball'
|
||||
@echo ' tarzst-pkg - Build the kernel as a zstd compressed tarball'
|
||||
@echo ' modules-cpio-pkg - Build the kernel modules as cpio archive'
|
||||
@echo ' (uses INSTALL_MOD_PATH inside the archive)'
|
||||
@echo ' perf-tar-src-pkg - Build the perf source tarball with no compression'
|
||||
@echo ' perf-targz-src-pkg - Build the perf source tarball with gzip compression'
|
||||
@echo ' perf-tarbz2-src-pkg - Build the perf source tarball with bz2 compression'
|
||||
|
||||
@@ -58,7 +58,7 @@ static bool allow_missing_ns_imports;
|
||||
|
||||
static bool error_occurred;
|
||||
|
||||
static bool extra_warn;
|
||||
static bool extra_warn __attribute__((unused));
|
||||
|
||||
bool target_is_big_endian;
|
||||
bool host_is_big_endian;
|
||||
|
||||
@@ -7680,6 +7680,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
||||
SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3911, "Lenovo Yoga Pro 7 14IAH10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC),
|
||||
SND_PCI_QUIRK(0x17aa, 0x391a, "Lenovo Yoga Slim 7 14AKP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
|
||||
SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TXNW2781_I2C),
|
||||
|
||||
@@ -313,7 +313,6 @@ enum {
|
||||
ALC897_FIXUP_HEADSET_MIC_PIN2,
|
||||
ALC897_FIXUP_UNIS_H3C_X500S,
|
||||
ALC897_FIXUP_HEADSET_MIC_PIN3,
|
||||
ALC897_FIXUP_H610M_HP_PIN,
|
||||
};
|
||||
|
||||
static const struct hda_fixup alc662_fixups[] = {
|
||||
@@ -767,13 +766,6 @@ static const struct hda_fixup alc662_fixups[] = {
|
||||
{ }
|
||||
},
|
||||
},
|
||||
[ALC897_FIXUP_H610M_HP_PIN] = {
|
||||
.type = HDA_FIXUP_PINS,
|
||||
.v.pins = (const struct hda_pintbl[]) {
|
||||
{ 0x19, 0x0321403f }, /* HP out */
|
||||
{ }
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct hda_quirk alc662_fixup_tbl[] = {
|
||||
@@ -823,7 +815,6 @@ static const struct hda_quirk alc662_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
|
||||
SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
|
||||
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
|
||||
SND_PCI_QUIRK(0x1458, 0xa194, "H610M H V2 DDR4", ALC897_FIXUP_H610M_HP_PIN),
|
||||
SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
|
||||
SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
|
||||
SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN),
|
||||
|
||||
@@ -295,6 +295,9 @@ enum {
|
||||
#define AZX_DCAPS_INTEL_LNL \
|
||||
(AZX_DCAPS_INTEL_SKYLAKE | AZX_DCAPS_PIO_COMMANDS)
|
||||
|
||||
#define AZX_DCAPS_INTEL_NVL \
|
||||
(AZX_DCAPS_INTEL_LNL & ~AZX_DCAPS_NO_ALIGN_BUFSIZE)
|
||||
|
||||
/* quirks for ATI SB / AMD Hudson */
|
||||
#define AZX_DCAPS_PRESET_ATI_SB \
|
||||
(AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB |\
|
||||
@@ -2565,8 +2568,8 @@ static const struct pci_device_id azx_ids[] = {
|
||||
/* Wildcat Lake */
|
||||
{ PCI_DEVICE_DATA(INTEL, HDA_WCL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
|
||||
/* Nova Lake */
|
||||
{ PCI_DEVICE_DATA(INTEL, HDA_NVL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, HDA_NVL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, HDA_NVL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_NVL) },
|
||||
{ PCI_DEVICE_DATA(INTEL, HDA_NVL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_NVL) },
|
||||
/* Apollolake (Broxton-P) */
|
||||
{ PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) },
|
||||
/* Gemini-Lake */
|
||||
|
||||
@@ -99,17 +99,33 @@ static const struct dmi_system_id soc_sdw_quirk_table[] = {
|
||||
.callback = soc_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "21YW"),
|
||||
DMI_MATCH(DMI_PRODUCT_SKU, "21YW"),
|
||||
},
|
||||
.driver_data = (void *)(ASOC_SDW_CODEC_SPKR),
|
||||
.driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)),
|
||||
},
|
||||
{
|
||||
.callback = soc_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "21YX"),
|
||||
DMI_MATCH(DMI_PRODUCT_SKU, "21YX"),
|
||||
},
|
||||
.driver_data = (void *)(ASOC_SDW_CODEC_SPKR),
|
||||
.driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)),
|
||||
},
|
||||
{
|
||||
.callback = soc_sdw_quirk_cb,
|
||||
.matches = { /* Lenovo P16s G5 AMD */
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_SKU, "21XG"),
|
||||
},
|
||||
.driver_data = (void *)(ASOC_SDW_ACP_DMIC),
|
||||
},
|
||||
{
|
||||
.callback = soc_sdw_quirk_cb,
|
||||
.matches = { /* Lenovo P16s G5 AMD */
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_SKU, "21XH"),
|
||||
},
|
||||
.driver_data = (void *)(ASOC_SDW_ACP_DMIC),
|
||||
},
|
||||
{
|
||||
.callback = soc_sdw_quirk_cb,
|
||||
|
||||
@@ -142,7 +142,7 @@ static bool nau8325_readable_reg(struct device *dev, unsigned int reg)
|
||||
static bool nau8325_writeable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case NAU8325_R00_HARDWARE_RST:
|
||||
case NAU8325_R00_HARDWARE_RST ... NAU8325_R01_SOFTWARE_RST:
|
||||
case NAU8325_R03_CLK_CTRL ... NAU8325_R06_INT_CLR_STATUS:
|
||||
case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME:
|
||||
case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2:
|
||||
@@ -670,6 +670,12 @@ static void nau8325_reset_chip(struct regmap *regmap)
|
||||
regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0000);
|
||||
}
|
||||
|
||||
static void nau8325_software_reset(struct regmap *regmap)
|
||||
{
|
||||
regmap_write(regmap, NAU8325_R01_SOFTWARE_RST, 0x0000);
|
||||
regmap_write(regmap, NAU8325_R01_SOFTWARE_RST, 0x0000);
|
||||
}
|
||||
|
||||
static void nau8325_init_regs(struct nau8325 *nau8325)
|
||||
{
|
||||
struct regmap *regmap = nau8325->regmap;
|
||||
@@ -856,6 +862,7 @@ static int nau8325_i2c_probe(struct i2c_client *i2c)
|
||||
nau8325_print_device_properties(nau8325);
|
||||
|
||||
nau8325_reset_chip(nau8325->regmap);
|
||||
nau8325_software_reset(nau8325->regmap);
|
||||
ret = regmap_read(nau8325->regmap, NAU8325_R02_DEVICE_ID, &value);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "Failed to read device id (%d)", ret);
|
||||
|
||||
@@ -520,7 +520,8 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev)
|
||||
if (num_elems > max_ssps) {
|
||||
dev_err(adev->dev, "board supports only %d SSP, %d specified\n",
|
||||
max_ssps, num_elems);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (ssp_port = 0; ssp_port < num_elems; ssp_port++) {
|
||||
@@ -528,11 +529,13 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev)
|
||||
for_each_set_bit(tdm_slot, &tdm_slots, 16) {
|
||||
ret = avs_register_i2s_test_board(adev, ssp_port, tdm_slot);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
kfree(array);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach)
|
||||
|
||||
@@ -198,6 +198,14 @@ static int class_function_component_probe(struct snd_soc_component *component)
|
||||
return sdca_irq_populate(drv->function, component, core->irq_info);
|
||||
}
|
||||
|
||||
static void class_function_component_remove(struct snd_soc_component *component)
|
||||
{
|
||||
struct class_function_drv *drv = snd_soc_component_get_drvdata(component);
|
||||
struct sdca_class_drv *core = drv->core;
|
||||
|
||||
sdca_irq_cleanup(component->dev, drv->function, core->irq_info);
|
||||
}
|
||||
|
||||
static int class_function_set_jack(struct snd_soc_component *component,
|
||||
struct snd_soc_jack *jack, void *d)
|
||||
{
|
||||
@@ -209,6 +217,7 @@ static int class_function_set_jack(struct snd_soc_component *component,
|
||||
|
||||
static const struct snd_soc_component_driver class_function_component_drv = {
|
||||
.probe = class_function_component_probe,
|
||||
.remove = class_function_component_remove,
|
||||
.endianness = 1,
|
||||
};
|
||||
|
||||
@@ -402,6 +411,13 @@ static int class_function_probe(struct auxiliary_device *auxdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void class_function_remove(struct auxiliary_device *auxdev)
|
||||
{
|
||||
struct class_function_drv *drv = auxiliary_get_drvdata(auxdev);
|
||||
|
||||
sdca_irq_cleanup(drv->dev, drv->function, drv->core->irq_info);
|
||||
}
|
||||
|
||||
static int class_function_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
|
||||
@@ -550,6 +566,7 @@ static struct auxiliary_driver class_function_drv = {
|
||||
},
|
||||
|
||||
.probe = class_function_probe,
|
||||
.remove = class_function_remove,
|
||||
.id_table = class_function_id_table
|
||||
};
|
||||
module_auxiliary_driver(class_function_drv);
|
||||
|
||||
@@ -117,9 +117,7 @@ static irqreturn_t function_status_handler(int irq, void *data)
|
||||
|
||||
status = val;
|
||||
for_each_set_bit(mask, &status, BITS_PER_BYTE) {
|
||||
mask = 1 << mask;
|
||||
|
||||
switch (mask) {
|
||||
switch (BIT(mask)) {
|
||||
case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION:
|
||||
//FIXME: Add init writes
|
||||
break;
|
||||
@@ -140,7 +138,7 @@ static irqreturn_t function_status_handler(int irq, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
ret = regmap_write(interrupt->function_regmap, reg, val);
|
||||
ret = regmap_write(interrupt->function_regmap, reg, val & 0x7F);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to clear function status: %d\n", ret);
|
||||
goto error;
|
||||
@@ -252,8 +250,7 @@ static int sdca_irq_request_locked(struct device *dev,
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL, handler,
|
||||
IRQF_ONESHOT, name, data);
|
||||
ret = request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT, name, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -264,6 +261,22 @@ static int sdca_irq_request_locked(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sdca_irq_free_locked(struct device *dev, struct sdca_interrupt_info *info,
|
||||
int sdca_irq, const char *name, void *data)
|
||||
{
|
||||
int irq;
|
||||
|
||||
irq = regmap_irq_get_virq(info->irq_data, sdca_irq);
|
||||
if (irq < 0)
|
||||
return;
|
||||
|
||||
free_irq(irq, data);
|
||||
|
||||
info->irqs[sdca_irq].irq = 0;
|
||||
|
||||
dev_dbg(dev, "freed irq %d for %s\n", irq, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* sdca_irq_request - request an individual SDCA interrupt
|
||||
* @dev: Pointer to the struct device against which things should be allocated.
|
||||
@@ -302,6 +315,30 @@ int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *info,
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA");
|
||||
|
||||
/**
|
||||
* sdca_irq_free - free an individual SDCA interrupt
|
||||
* @dev: Pointer to the struct device.
|
||||
* @info: Pointer to the interrupt information structure.
|
||||
* @sdca_irq: SDCA interrupt position.
|
||||
* @name: Name to be given to the IRQ.
|
||||
* @data: Private data pointer that will be passed to the handler.
|
||||
*
|
||||
* Typically this is handled internally by sdca_irq_cleanup, however if
|
||||
* a device requires custom IRQ handling this can be called manually before
|
||||
* calling sdca_irq_cleanup, which will then skip that IRQ whilst processing.
|
||||
*/
|
||||
void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *info,
|
||||
int sdca_irq, const char *name, void *data)
|
||||
{
|
||||
if (sdca_irq < 0 || sdca_irq >= SDCA_MAX_INTERRUPTS)
|
||||
return;
|
||||
|
||||
guard(mutex)(&info->irq_lock);
|
||||
|
||||
sdca_irq_free_locked(dev, info, sdca_irq, name, data);
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(sdca_irq_free, "SND_SOC_SDCA");
|
||||
|
||||
/**
|
||||
* sdca_irq_data_populate - Populate common interrupt data
|
||||
* @dev: Pointer to the Function device.
|
||||
@@ -328,8 +365,8 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *regmap,
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
name = devm_kasprintf(dev, GFP_KERNEL, "%s %s %s", function->desc->name,
|
||||
entity->label, control->label);
|
||||
name = kasprintf(GFP_KERNEL, "%s %s %s", function->desc->name,
|
||||
entity->label, control->label);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -516,6 +553,35 @@ int sdca_irq_populate(struct sdca_function_data *function,
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA");
|
||||
|
||||
/**
|
||||
* sdca_irq_cleanup - Free all the individual IRQs for an SDCA Function
|
||||
* @sdev: Device pointer against which the sdca_interrupt_info was allocated.
|
||||
* @function: Pointer to the SDCA Function.
|
||||
* @info: Pointer to the SDCA interrupt info for this device.
|
||||
*
|
||||
* Typically this would be called from the driver for a single SDCA Function.
|
||||
*/
|
||||
void sdca_irq_cleanup(struct device *dev,
|
||||
struct sdca_function_data *function,
|
||||
struct sdca_interrupt_info *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
guard(mutex)(&info->irq_lock);
|
||||
|
||||
for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) {
|
||||
struct sdca_interrupt *interrupt = &info->irqs[i];
|
||||
|
||||
if (interrupt->function != function || !interrupt->irq)
|
||||
continue;
|
||||
|
||||
sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt);
|
||||
|
||||
kfree(interrupt->name);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA");
|
||||
|
||||
/**
|
||||
* sdca_irq_allocate - allocate an SDCA interrupt structure for a device
|
||||
* @sdev: Device pointer against which things should be allocated.
|
||||
|
||||
@@ -219,6 +219,7 @@ EXPORT_SYMBOL_NS(hda_dsp_pcm_pointer, "SND_SOC_SOF_INTEL_HDA_COMMON");
|
||||
int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
|
||||
struct snd_pcm_substream *substream)
|
||||
{
|
||||
const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata);
|
||||
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_soc_component *scomp = sdev->component;
|
||||
@@ -268,8 +269,17 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* minimum as per HDA spec */
|
||||
snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
|
||||
/*
|
||||
* Set period size constraint to ensure BDLE buffer length and
|
||||
* start address alignment requirements are met. Align to 128
|
||||
* bytes for newer Intel platforms, with older ones using 4 byte alignment.
|
||||
*/
|
||||
if (chip_info->hw_ip_version >= SOF_INTEL_ACE_4_0)
|
||||
snd_pcm_hw_constraint_step(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
|
||||
else
|
||||
snd_pcm_hw_constraint_step(substream->runtime, 0,
|
||||
SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
|
||||
|
||||
/* avoid circular buffer wrap in middle of period */
|
||||
snd_pcm_hw_constraint_integer(substream->runtime,
|
||||
|
||||
@@ -1133,8 +1133,7 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
|
||||
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
|
||||
|
||||
static bool is_endpoint_present(struct sdw_slave *sdw_device,
|
||||
struct asoc_sdw_codec_info *dai_info, int dai_type)
|
||||
static bool is_endpoint_present(struct sdw_slave *sdw_device, int dai_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1145,7 +1144,7 @@ static bool is_endpoint_present(struct sdw_slave *sdw_device,
|
||||
}
|
||||
|
||||
for (i = 0; i < sdw_device->sdca_data.num_functions; i++) {
|
||||
if (dai_type == dai_info->dais[i].dai_type)
|
||||
if (dai_type == asoc_sdw_get_dai_type(sdw_device->sdca_data.function[i].type))
|
||||
return true;
|
||||
}
|
||||
dev_dbg(&sdw_device->dev, "Endpoint DAI type %d not found\n", dai_type);
|
||||
@@ -1199,11 +1198,10 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
|
||||
}
|
||||
for (j = 0; j < codec_info_list[i].dai_num; j++) {
|
||||
/* Check if the endpoint is present by the SDCA DisCo table */
|
||||
if (!is_endpoint_present(sdw_device, &codec_info_list[i],
|
||||
codec_info_list[i].dais[j].dai_type))
|
||||
if (!is_endpoint_present(sdw_device, codec_info_list[i].dais[j].dai_type))
|
||||
continue;
|
||||
|
||||
endpoints[ep_index].num = ep_index;
|
||||
endpoints[ep_index].num = j;
|
||||
if (codec_info_list[i].dais[j].dai_type == SOC_SDW_DAI_TYPE_AMP) {
|
||||
/* Assume all amp are aggregated */
|
||||
endpoints[ep_index].aggregated = 1;
|
||||
|
||||
@@ -802,6 +802,7 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
|
||||
break;
|
||||
/* Left justified */
|
||||
case SND_SOC_DAIFMT_MSB:
|
||||
cr1 |= SAI_XCR1_CKSTR;
|
||||
frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF;
|
||||
break;
|
||||
/* Right justified */
|
||||
@@ -809,9 +810,11 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
|
||||
frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
cr1 |= SAI_XCR1_CKSTR;
|
||||
frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF;
|
||||
break;
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
cr1 |= SAI_XCR1_CKSTR;
|
||||
frcr |= SAI_XFRCR_FSPOL;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -397,30 +397,24 @@ struct prctl_mm_map {
|
||||
# define PR_RSEQ_SLICE_EXT_ENABLE 0x01
|
||||
|
||||
/*
|
||||
* Get the current indirect branch tracking configuration for the current
|
||||
* thread, this will be the value configured via PR_SET_INDIR_BR_LP_STATUS.
|
||||
* Get or set the control flow integrity (CFI) configuration for the
|
||||
* current thread.
|
||||
*
|
||||
* Some per-thread control flow integrity settings are not yet
|
||||
* controlled through this prctl(); see for example
|
||||
* PR_{GET,SET,LOCK}_SHADOW_STACK_STATUS
|
||||
*/
|
||||
#define PR_GET_INDIR_BR_LP_STATUS 80
|
||||
|
||||
#define PR_GET_CFI 80
|
||||
#define PR_SET_CFI 81
|
||||
/*
|
||||
* Set the indirect branch tracking configuration. PR_INDIR_BR_LP_ENABLE will
|
||||
* enable cpu feature for user thread, to track all indirect branches and ensure
|
||||
* they land on arch defined landing pad instruction.
|
||||
* x86 - If enabled, an indirect branch must land on an ENDBRANCH instruction.
|
||||
* arch64 - If enabled, an indirect branch must land on a BTI instruction.
|
||||
* riscv - If enabled, an indirect branch must land on an lpad instruction.
|
||||
* PR_INDIR_BR_LP_DISABLE will disable feature for user thread and indirect
|
||||
* branches will no more be tracked by cpu to land on arch defined landing pad
|
||||
* instruction.
|
||||
* Forward-edge CFI variants (excluding ARM64 BTI, which has its own
|
||||
* prctl()s).
|
||||
*/
|
||||
#define PR_SET_INDIR_BR_LP_STATUS 81
|
||||
# define PR_INDIR_BR_LP_ENABLE (1UL << 0)
|
||||
#define PR_CFI_BRANCH_LANDING_PADS 0
|
||||
/* Return and control values for PR_{GET,SET}_CFI */
|
||||
# define PR_CFI_ENABLE _BITUL(0)
|
||||
# define PR_CFI_DISABLE _BITUL(1)
|
||||
# define PR_CFI_LOCK _BITUL(2)
|
||||
|
||||
/*
|
||||
* Prevent further changes to the specified indirect branch tracking
|
||||
* configuration. All bits may be locked via this call, including
|
||||
* undefined bits.
|
||||
*/
|
||||
#define PR_LOCK_INDIR_BR_LP_STATUS 82
|
||||
|
||||
#endif /* _LINUX_PRCTL_H */
|
||||
@@ -2409,7 +2409,7 @@ struct topo_params {
|
||||
int max_l3_id;
|
||||
int max_node_num;
|
||||
int nodes_per_pkg;
|
||||
int cores_per_node;
|
||||
int cores_per_pkg;
|
||||
int threads_per_core;
|
||||
} topo;
|
||||
|
||||
@@ -2837,30 +2837,29 @@ static inline int print_name(int width, int *printed, char *delim, char *name, e
|
||||
UNUSED(type);
|
||||
|
||||
if (format == FORMAT_RAW && width >= 64)
|
||||
return (sprintf(outp, "%s%-8s", (*printed++ ? delim : ""), name));
|
||||
return (sprintf(outp, "%s%-8s", ((*printed)++ ? delim : ""), name));
|
||||
else
|
||||
return (sprintf(outp, "%s%s", (*printed++ ? delim : ""), name));
|
||||
return (sprintf(outp, "%s%s", ((*printed)++ ? delim : ""), name));
|
||||
}
|
||||
|
||||
static inline int print_hex_value(int width, int *printed, char *delim, unsigned long long value)
|
||||
{
|
||||
if (width <= 32)
|
||||
return (sprintf(outp, "%s%08x", (*printed++ ? delim : ""), (unsigned int)value));
|
||||
return (sprintf(outp, "%s%08x", ((*printed)++ ? delim : ""), (unsigned int)value));
|
||||
else
|
||||
return (sprintf(outp, "%s%016llx", (*printed++ ? delim : ""), value));
|
||||
return (sprintf(outp, "%s%016llx", ((*printed)++ ? delim : ""), value));
|
||||
}
|
||||
|
||||
static inline int print_decimal_value(int width, int *printed, char *delim, unsigned long long value)
|
||||
{
|
||||
if (width <= 32)
|
||||
return (sprintf(outp, "%s%d", (*printed++ ? delim : ""), (unsigned int)value));
|
||||
else
|
||||
return (sprintf(outp, "%s%-8lld", (*printed++ ? delim : ""), value));
|
||||
UNUSED(width);
|
||||
|
||||
return (sprintf(outp, "%s%lld", ((*printed)++ ? delim : ""), value));
|
||||
}
|
||||
|
||||
static inline int print_float_value(int *printed, char *delim, double value)
|
||||
{
|
||||
return (sprintf(outp, "%s%0.2f", (*printed++ ? delim : ""), value));
|
||||
return (sprintf(outp, "%s%0.2f", ((*printed)++ ? delim : ""), value));
|
||||
}
|
||||
|
||||
void print_header(char *delim)
|
||||
@@ -3469,7 +3468,7 @@ int format_counters(PER_THREAD_PARAMS)
|
||||
for (i = 0, pp = sys.perf_tp; pp; ++i, pp = pp->next) {
|
||||
if (pp->format == FORMAT_RAW)
|
||||
outp += print_hex_value(pp->width, &printed, delim, t->perf_counter[i]);
|
||||
else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)
|
||||
else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE)
|
||||
outp += print_decimal_value(pp->width, &printed, delim, t->perf_counter[i]);
|
||||
else if (pp->format == FORMAT_PERCENT) {
|
||||
if (pp->type == COUNTER_USEC)
|
||||
@@ -3490,12 +3489,12 @@ int format_counters(PER_THREAD_PARAMS)
|
||||
|
||||
case PMT_TYPE_XTAL_TIME:
|
||||
value_converted = pct(value_raw / crystal_hz, interval_float);
|
||||
outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);
|
||||
outp += print_float_value(&printed, delim, value_converted);
|
||||
break;
|
||||
|
||||
case PMT_TYPE_TCORE_CLOCK:
|
||||
value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float);
|
||||
outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);
|
||||
outp += print_float_value(&printed, delim, value_converted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3539,7 +3538,7 @@ int format_counters(PER_THREAD_PARAMS)
|
||||
for (i = 0, pp = sys.perf_cp; pp; i++, pp = pp->next) {
|
||||
if (pp->format == FORMAT_RAW)
|
||||
outp += print_hex_value(pp->width, &printed, delim, c->perf_counter[i]);
|
||||
else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)
|
||||
else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE)
|
||||
outp += print_decimal_value(pp->width, &printed, delim, c->perf_counter[i]);
|
||||
else if (pp->format == FORMAT_PERCENT)
|
||||
outp += print_float_value(&printed, delim, pct(c->perf_counter[i], tsc));
|
||||
@@ -3695,7 +3694,7 @@ int format_counters(PER_THREAD_PARAMS)
|
||||
outp += print_hex_value(pp->width, &printed, delim, p->perf_counter[i]);
|
||||
else if (pp->type == COUNTER_K2M)
|
||||
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), (unsigned int)p->perf_counter[i] / 1000);
|
||||
else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)
|
||||
else if (pp->format == FORMAT_DELTA || pp->format == FORMAT_AVERAGE)
|
||||
outp += print_decimal_value(pp->width, &printed, delim, p->perf_counter[i]);
|
||||
else if (pp->format == FORMAT_PERCENT)
|
||||
outp += print_float_value(&printed, delim, pct(p->perf_counter[i], tsc));
|
||||
@@ -9122,10 +9121,13 @@ void process_cpuid()
|
||||
cpuid_has_hv = ecx_flags & (1 << 31);
|
||||
|
||||
if (!no_msr) {
|
||||
if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))
|
||||
if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) {
|
||||
warnx("get_msr(UCODE)");
|
||||
else
|
||||
} else {
|
||||
ucode_patch_valid = true;
|
||||
if (!authentic_amd && !hygon_genuine)
|
||||
ucode_patch >>= 32;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -9139,7 +9141,7 @@ void process_cpuid()
|
||||
if (!quiet) {
|
||||
fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)", family, model, stepping, family, model, stepping);
|
||||
if (ucode_patch_valid)
|
||||
fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));
|
||||
fprintf(outf, " microcode 0x%x", (unsigned int)ucode_patch);
|
||||
fputc('\n', outf);
|
||||
|
||||
fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level);
|
||||
@@ -9403,13 +9405,13 @@ void perf_l2_init(void)
|
||||
if (!is_hybrid) {
|
||||
fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP);
|
||||
if (fd_l2_percpu[cpu] == -1) {
|
||||
err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs);
|
||||
warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs);
|
||||
free_fd_l2_percpu();
|
||||
return;
|
||||
}
|
||||
retval = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);
|
||||
if (retval == -1) {
|
||||
err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits);
|
||||
warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits);
|
||||
free_fd_l2_percpu();
|
||||
return;
|
||||
}
|
||||
@@ -9418,39 +9420,39 @@ void perf_l2_init(void)
|
||||
if (perf_pcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_pcore_set)) {
|
||||
fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP);
|
||||
if (fd_l2_percpu[cpu] == -1) {
|
||||
err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs);
|
||||
warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs);
|
||||
free_fd_l2_percpu();
|
||||
return;
|
||||
}
|
||||
retval = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);
|
||||
if (retval == -1) {
|
||||
err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits);
|
||||
warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits);
|
||||
free_fd_l2_percpu();
|
||||
return;
|
||||
}
|
||||
} else if (perf_ecore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_ecore_set)) {
|
||||
fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.refs, -1, PERF_FORMAT_GROUP);
|
||||
if (fd_l2_percpu[cpu] == -1) {
|
||||
err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.refs);
|
||||
warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.refs);
|
||||
free_fd_l2_percpu();
|
||||
return;
|
||||
}
|
||||
retval = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);
|
||||
if (retval == -1) {
|
||||
err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.hits);
|
||||
warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.hits);
|
||||
free_fd_l2_percpu();
|
||||
return;
|
||||
}
|
||||
} else if (perf_lcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_lcore_set)) {
|
||||
fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.refs, -1, PERF_FORMAT_GROUP);
|
||||
if (fd_l2_percpu[cpu] == -1) {
|
||||
err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.refs);
|
||||
warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.refs);
|
||||
free_fd_l2_percpu();
|
||||
return;
|
||||
}
|
||||
retval = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);
|
||||
if (retval == -1) {
|
||||
err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.hits);
|
||||
warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.hits);
|
||||
free_fd_l2_percpu();
|
||||
return;
|
||||
}
|
||||
@@ -9634,9 +9636,9 @@ void topology_probe(bool startup)
|
||||
topo.max_core_id = max_core_id; /* within a package */
|
||||
topo.max_package_id = max_package_id;
|
||||
|
||||
topo.cores_per_node = max_core_id + 1;
|
||||
topo.cores_per_pkg = max_core_id + 1;
|
||||
if (debug > 1)
|
||||
fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node);
|
||||
fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_pkg);
|
||||
if (!summary_only)
|
||||
BIC_PRESENT(BIC_Core);
|
||||
|
||||
@@ -9701,14 +9703,13 @@ error:
|
||||
void allocate_counters(struct counters *counters)
|
||||
{
|
||||
int i;
|
||||
int num_cores = topo.cores_per_node * topo.nodes_per_pkg * topo.num_packages;
|
||||
int num_threads = topo.threads_per_core * num_cores;
|
||||
int num_cores = topo.cores_per_pkg * topo.num_packages;
|
||||
|
||||
counters->threads = calloc(num_threads, sizeof(struct thread_data));
|
||||
counters->threads = calloc(topo.max_cpu_num + 1, sizeof(struct thread_data));
|
||||
if (counters->threads == NULL)
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < num_threads; i++)
|
||||
for (i = 0; i < topo.max_cpu_num + 1; i++)
|
||||
(counters->threads)[i].cpu_id = -1;
|
||||
|
||||
counters->cores = calloc(num_cores, sizeof(struct core_data));
|
||||
@@ -11284,6 +11285,14 @@ void probe_cpuidle_residency(void)
|
||||
}
|
||||
}
|
||||
|
||||
static bool cpuidle_counter_wanted(char *name)
|
||||
{
|
||||
if (is_deferred_skip(name))
|
||||
return false;
|
||||
|
||||
return DO_BIC(BIC_cpuidle) || is_deferred_add(name);
|
||||
}
|
||||
|
||||
void probe_cpuidle_counts(void)
|
||||
{
|
||||
char path[64];
|
||||
@@ -11293,7 +11302,7 @@ void probe_cpuidle_counts(void)
|
||||
int min_state = 1024, max_state = 0;
|
||||
char *sp;
|
||||
|
||||
if (!DO_BIC(BIC_cpuidle))
|
||||
if (!DO_BIC(BIC_cpuidle) && !deferred_add_index)
|
||||
return;
|
||||
|
||||
for (state = 10; state >= 0; --state) {
|
||||
@@ -11308,12 +11317,6 @@ void probe_cpuidle_counts(void)
|
||||
|
||||
remove_underbar(name_buf);
|
||||
|
||||
if (!DO_BIC(BIC_cpuidle) && !is_deferred_add(name_buf))
|
||||
continue;
|
||||
|
||||
if (is_deferred_skip(name_buf))
|
||||
continue;
|
||||
|
||||
/* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
|
||||
sp = strchr(name_buf, '-');
|
||||
if (!sp)
|
||||
@@ -11328,16 +11331,19 @@ void probe_cpuidle_counts(void)
|
||||
* Add 'C1+' for C1, and so on. The 'below' sysfs file always contains 0 for
|
||||
* the last state, so do not add it.
|
||||
*/
|
||||
|
||||
*sp = '+';
|
||||
*(sp + 1) = '\0';
|
||||
sprintf(path, "cpuidle/state%d/below", state);
|
||||
add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);
|
||||
if (cpuidle_counter_wanted(name_buf)) {
|
||||
sprintf(path, "cpuidle/state%d/below", state);
|
||||
add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);
|
||||
}
|
||||
}
|
||||
|
||||
*sp = '\0';
|
||||
sprintf(path, "cpuidle/state%d/usage", state);
|
||||
add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);
|
||||
if (cpuidle_counter_wanted(name_buf)) {
|
||||
sprintf(path, "cpuidle/state%d/usage", state);
|
||||
add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The 'above' sysfs file always contains 0 for the shallowest state (smallest
|
||||
@@ -11346,8 +11352,10 @@ void probe_cpuidle_counts(void)
|
||||
if (state != min_state) {
|
||||
*sp = '-';
|
||||
*(sp + 1) = '\0';
|
||||
sprintf(path, "cpuidle/state%d/above", state);
|
||||
add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);
|
||||
if (cpuidle_counter_wanted(name_buf)) {
|
||||
sprintf(path, "cpuidle/state%d/above", state);
|
||||
add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,9 +94,9 @@ bool cfi_ptrace_test(void)
|
||||
}
|
||||
|
||||
switch (ptrace_test_num) {
|
||||
#define CFI_ENABLE_MASK (PTRACE_CFI_LP_EN_STATE | \
|
||||
PTRACE_CFI_SS_EN_STATE | \
|
||||
PTRACE_CFI_SS_PTR_STATE)
|
||||
#define CFI_ENABLE_MASK (PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE | \
|
||||
PTRACE_CFI_SHADOW_STACK_EN_STATE | \
|
||||
PTRACE_CFI_SHADOW_STACK_PTR_STATE)
|
||||
case 0:
|
||||
if ((cfi_reg.cfi_status.cfi_state & CFI_ENABLE_MASK) != CFI_ENABLE_MASK)
|
||||
ksft_exit_fail_msg("%s: ptrace_getregset failed, %llu\n", __func__,
|
||||
@@ -106,7 +106,8 @@ bool cfi_ptrace_test(void)
|
||||
__func__);
|
||||
break;
|
||||
case 1:
|
||||
if (!(cfi_reg.cfi_status.cfi_state & PTRACE_CFI_ELP_STATE))
|
||||
if (!(cfi_reg.cfi_status.cfi_state &
|
||||
PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE))
|
||||
ksft_exit_fail_msg("%s: elp must have been set\n", __func__);
|
||||
/* clear elp state. not interested in anything else */
|
||||
cfi_reg.cfi_status.cfi_state = 0;
|
||||
@@ -145,11 +146,11 @@ int main(int argc, char *argv[])
|
||||
* pads for user mode except lighting up a bit in senvcfg via a prctl.
|
||||
* Enable landing pad support throughout the execution of the test binary.
|
||||
*/
|
||||
ret = my_syscall5(__NR_prctl, PR_GET_INDIR_BR_LP_STATUS, &lpad_status, 0, 0, 0);
|
||||
ret = my_syscall5(__NR_prctl, PR_GET_CFI, PR_CFI_BRANCH_LANDING_PADS, &lpad_status, 0, 0);
|
||||
if (ret)
|
||||
ksft_exit_fail_msg("Get landing pad status failed with %d\n", ret);
|
||||
|
||||
if (!(lpad_status & PR_INDIR_BR_LP_ENABLE))
|
||||
if (!(lpad_status & PR_CFI_ENABLE))
|
||||
ksft_exit_fail_msg("Landing pad is not enabled, should be enabled via glibc\n");
|
||||
|
||||
ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS, &ss_status, 0, 0, 0);
|
||||
|
||||
Reference in new issue
Block a user