mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-25 20:10:23 +09:00
Merge 3b9de981fe ("wifi: iwlwifi: pcie: fix NULL pointer dereference in iwl_pcie_irq_rx_msix_handler()") into android14-5.15-lts
Steps on the way to 5.15.121 Change-Id: I46d1f8e6c6354c807e3b59864eb2dff2b4564a2a Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -326,6 +326,23 @@
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Raw SMP data memory barrier
|
||||
*/
|
||||
.macro __smp_dmb mode
|
||||
#if __LINUX_ARM_ARCH__ >= 7
|
||||
.ifeqs "\mode","arm"
|
||||
dmb ish
|
||||
.else
|
||||
W(dmb) ish
|
||||
.endif
|
||||
#elif __LINUX_ARM_ARCH__ == 6
|
||||
mcr p15, 0, r0, c7, c10, 5 @ dmb
|
||||
#else
|
||||
.error "Incompatible SMP platform"
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#if defined(CONFIG_CPU_V7M)
|
||||
/*
|
||||
* setmode is used to assert to be in svc mode during boot. For v7-M
|
||||
|
||||
@@ -14,14 +14,35 @@
|
||||
* ops which are SMP safe even on a UP kernel.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Unordered
|
||||
*/
|
||||
|
||||
#define sync_set_bit(nr, p) _set_bit(nr, p)
|
||||
#define sync_clear_bit(nr, p) _clear_bit(nr, p)
|
||||
#define sync_change_bit(nr, p) _change_bit(nr, p)
|
||||
#define sync_test_and_set_bit(nr, p) _test_and_set_bit(nr, p)
|
||||
#define sync_test_and_clear_bit(nr, p) _test_and_clear_bit(nr, p)
|
||||
#define sync_test_and_change_bit(nr, p) _test_and_change_bit(nr, p)
|
||||
#define sync_test_bit(nr, addr) test_bit(nr, addr)
|
||||
#define arch_sync_cmpxchg arch_cmpxchg
|
||||
|
||||
/*
|
||||
* Fully ordered
|
||||
*/
|
||||
|
||||
int _sync_test_and_set_bit(int nr, volatile unsigned long * p);
|
||||
#define sync_test_and_set_bit(nr, p) _sync_test_and_set_bit(nr, p)
|
||||
|
||||
int _sync_test_and_clear_bit(int nr, volatile unsigned long * p);
|
||||
#define sync_test_and_clear_bit(nr, p) _sync_test_and_clear_bit(nr, p)
|
||||
|
||||
int _sync_test_and_change_bit(int nr, volatile unsigned long * p);
|
||||
#define sync_test_and_change_bit(nr, p) _sync_test_and_change_bit(nr, p)
|
||||
|
||||
#define arch_sync_cmpxchg(ptr, old, new) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) __ret; \
|
||||
__smp_mb__before_atomic(); \
|
||||
__ret = arch_cmpxchg_relaxed((ptr), (old), (new)); \
|
||||
__smp_mb__after_atomic(); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@ UNWIND( .fnend )
|
||||
ENDPROC(\name )
|
||||
.endm
|
||||
|
||||
.macro testop, name, instr, store
|
||||
.macro __testop, name, instr, store, barrier
|
||||
ENTRY( \name )
|
||||
UNWIND( .fnstart )
|
||||
ands ip, r1, #3
|
||||
@@ -38,7 +38,7 @@ UNWIND( .fnstart )
|
||||
mov r0, r0, lsr #5
|
||||
add r1, r1, r0, lsl #2 @ Get word offset
|
||||
mov r3, r2, lsl r3 @ create mask
|
||||
smp_dmb
|
||||
\barrier
|
||||
#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
|
||||
.arch_extension mp
|
||||
ALT_SMP(W(pldw) [r1])
|
||||
@@ -50,13 +50,21 @@ UNWIND( .fnstart )
|
||||
strex ip, r2, [r1]
|
||||
cmp ip, #0
|
||||
bne 1b
|
||||
smp_dmb
|
||||
\barrier
|
||||
cmp r0, #0
|
||||
movne r0, #1
|
||||
2: bx lr
|
||||
UNWIND( .fnend )
|
||||
ENDPROC(\name )
|
||||
.endm
|
||||
|
||||
.macro testop, name, instr, store
|
||||
__testop \name, \instr, \store, smp_dmb
|
||||
.endm
|
||||
|
||||
.macro sync_testop, name, instr, store
|
||||
__testop \name, \instr, \store, __smp_dmb
|
||||
.endm
|
||||
#else
|
||||
.macro bitop, name, instr
|
||||
ENTRY( \name )
|
||||
|
||||
@@ -10,3 +10,7 @@
|
||||
.text
|
||||
|
||||
testop _test_and_change_bit, eor, str
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
sync_testop _sync_test_and_change_bit, eor, str
|
||||
#endif
|
||||
|
||||
@@ -10,3 +10,7 @@
|
||||
.text
|
||||
|
||||
testop _test_and_clear_bit, bicne, strne
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
sync_testop _sync_test_and_clear_bit, bicne, strne
|
||||
#endif
|
||||
|
||||
@@ -10,3 +10,7 @@
|
||||
.text
|
||||
|
||||
testop _test_and_set_bit, orreq, streq
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 6
|
||||
sync_testop _sync_test_and_set_bit, orreq, streq
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@ enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn,
|
||||
* Different from other insn uses imm8, the real addressing offset of
|
||||
* STRD in T32 encoding should be imm8 * 4. See ARMARM description.
|
||||
*/
|
||||
enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn,
|
||||
static enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn,
|
||||
struct arch_probes_insn *asi,
|
||||
const struct decode_header *h)
|
||||
{
|
||||
|
||||
@@ -233,7 +233,7 @@ singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
|
||||
* kprobe, and that level is reserved for user kprobe handlers, so we can't
|
||||
* risk encountering a new kprobe in an interrupt handler.
|
||||
*/
|
||||
void __kprobes kprobe_handler(struct pt_regs *regs)
|
||||
static void __kprobes kprobe_handler(struct pt_regs *regs)
|
||||
{
|
||||
struct kprobe *p, *cur;
|
||||
struct kprobe_ctlblk *kcb;
|
||||
|
||||
@@ -145,8 +145,6 @@ __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty)
|
||||
}
|
||||
}
|
||||
|
||||
extern void kprobe_handler(struct pt_regs *regs);
|
||||
|
||||
static void
|
||||
optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
@@ -720,7 +720,7 @@ static const char coverage_register_lookup[16] = {
|
||||
[REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP,
|
||||
};
|
||||
|
||||
unsigned coverage_start_registers(const struct decode_header *h)
|
||||
static unsigned coverage_start_registers(const struct decode_header *h)
|
||||
{
|
||||
unsigned regs = 0;
|
||||
int i;
|
||||
|
||||
@@ -454,3 +454,7 @@ void kprobe_thumb32_test_cases(void);
|
||||
#else
|
||||
void kprobe_arm_test_cases(void);
|
||||
#endif
|
||||
|
||||
void __kprobes_test_case_start(void);
|
||||
void __kprobes_test_case_end_16(void);
|
||||
void __kprobes_test_case_end_32(void);
|
||||
|
||||
@@ -364,7 +364,7 @@ static int amd_pmu_hw_config(struct perf_event *event)
|
||||
|
||||
/* pass precise event sampling to ibs: */
|
||||
if (event->attr.precise_ip && get_ibs_caps())
|
||||
return -ENOENT;
|
||||
return forward_event_to_ibs(event);
|
||||
|
||||
if (has_branch_stack(event))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@@ -194,7 +194,7 @@ static struct perf_ibs *get_ibs_pmu(int type)
|
||||
}
|
||||
|
||||
/*
|
||||
* Use IBS for precise event sampling:
|
||||
* core pmu config -> IBS config
|
||||
*
|
||||
* perf record -a -e cpu-cycles:p ... # use ibs op counting cycle count
|
||||
* perf record -a -e r076:p ... # same as -e cpu-cycles:p
|
||||
@@ -203,25 +203,9 @@ static struct perf_ibs *get_ibs_pmu(int type)
|
||||
* IbsOpCntCtl (bit 19) of IBS Execution Control Register (IbsOpCtl,
|
||||
* MSRC001_1033) is used to select either cycle or micro-ops counting
|
||||
* mode.
|
||||
*
|
||||
* The rip of IBS samples has skid 0. Thus, IBS supports precise
|
||||
* levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the
|
||||
* rip is invalid when IBS was not able to record the rip correctly.
|
||||
* We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then.
|
||||
*
|
||||
*/
|
||||
static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
|
||||
static int core_pmu_ibs_config(struct perf_event *event, u64 *config)
|
||||
{
|
||||
switch (event->attr.precise_ip) {
|
||||
case 0:
|
||||
return -ENOENT;
|
||||
case 1:
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (event->attr.type) {
|
||||
case PERF_TYPE_HARDWARE:
|
||||
switch (event->attr.config) {
|
||||
@@ -247,22 +231,37 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/*
|
||||
* The rip of IBS samples has skid 0. Thus, IBS supports precise
|
||||
* levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the
|
||||
* rip is invalid when IBS was not able to record the rip correctly.
|
||||
* We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then.
|
||||
*/
|
||||
int forward_event_to_ibs(struct perf_event *event)
|
||||
{
|
||||
u64 config = 0;
|
||||
|
||||
if (!event->attr.precise_ip || event->attr.precise_ip > 2)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!core_pmu_ibs_config(event, &config)) {
|
||||
event->attr.type = perf_ibs_op.pmu.type;
|
||||
event->attr.config = config;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int perf_ibs_init(struct perf_event *event)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct perf_ibs *perf_ibs;
|
||||
u64 max_cnt, config;
|
||||
int ret;
|
||||
|
||||
perf_ibs = get_ibs_pmu(event->attr.type);
|
||||
if (perf_ibs) {
|
||||
config = event->attr.config;
|
||||
} else {
|
||||
perf_ibs = &perf_ibs_op;
|
||||
ret = perf_ibs_precise_event(event, &config);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (!perf_ibs)
|
||||
return -ENOENT;
|
||||
|
||||
config = event->attr.config;
|
||||
|
||||
if (event->pmu != &perf_ibs->pmu)
|
||||
return -ENOENT;
|
||||
|
||||
@@ -427,8 +427,10 @@ struct pebs_xmm {
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
extern u32 get_ibs_caps(void);
|
||||
extern int forward_event_to_ibs(struct perf_event *event);
|
||||
#else
|
||||
static inline u32 get_ibs_caps(void) { return 0; }
|
||||
static inline int forward_event_to_ibs(struct perf_event *event) { return -ENOENT; }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
|
||||
@@ -235,8 +235,8 @@ static inline void native_pgd_clear(pgd_t *pgd)
|
||||
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) })
|
||||
#define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val((pmd)) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val })
|
||||
#define __swp_entry_to_pmd(x) ((pmd_t) { .pmd = (x).val })
|
||||
#define __swp_entry_to_pte(x) (__pte((x).val))
|
||||
#define __swp_entry_to_pmd(x) (__pmd((x).val))
|
||||
|
||||
extern int kern_addr_valid(unsigned long addr);
|
||||
extern void cleanup_highmap(void);
|
||||
|
||||
@@ -731,11 +731,15 @@ unlock:
|
||||
static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s)
|
||||
{
|
||||
struct task_struct *p, *t;
|
||||
pid_t pid;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_process_thread(p, t) {
|
||||
if (is_closid_match(t, r) || is_rmid_match(t, r))
|
||||
seq_printf(s, "%d\n", t->pid);
|
||||
if (is_closid_match(t, r) || is_rmid_match(t, r)) {
|
||||
pid = task_pid_vnr(t);
|
||||
if (pid)
|
||||
seq_printf(s, "%d\n", pid);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@@ -2448,6 +2448,7 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime,
|
||||
u32 hwi, adj_step;
|
||||
s64 margin;
|
||||
u64 cost, new_inuse;
|
||||
unsigned long flags;
|
||||
|
||||
current_hweight(iocg, NULL, &hwi);
|
||||
old_hwi = hwi;
|
||||
@@ -2466,11 +2467,11 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime,
|
||||
iocg->inuse == iocg->active)
|
||||
return cost;
|
||||
|
||||
spin_lock_irq(&ioc->lock);
|
||||
spin_lock_irqsave(&ioc->lock, flags);
|
||||
|
||||
/* we own inuse only when @iocg is in the normal active state */
|
||||
if (iocg->abs_vdebt || list_empty(&iocg->active_list)) {
|
||||
spin_unlock_irq(&ioc->lock);
|
||||
spin_unlock_irqrestore(&ioc->lock, flags);
|
||||
return cost;
|
||||
}
|
||||
|
||||
@@ -2491,7 +2492,7 @@ static u64 adjust_inuse_and_calc_cost(struct ioc_gq *iocg, u64 vtime,
|
||||
} while (time_after64(vtime + cost, now->vnow) &&
|
||||
iocg->inuse != iocg->active);
|
||||
|
||||
spin_unlock_irq(&ioc->lock);
|
||||
spin_unlock_irqrestore(&ioc->lock, flags);
|
||||
|
||||
TRACE_IOCG_PATH(inuse_adjust, iocg, now,
|
||||
old_inuse, iocg->inuse, old_hwi, hwi);
|
||||
|
||||
@@ -2860,10 +2860,10 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state,
|
||||
|
||||
err = of_property_read_u32(state_node, "min-residency-us", &residency);
|
||||
if (!err)
|
||||
genpd_state->residency_ns = 1000 * residency;
|
||||
genpd_state->residency_ns = 1000LL * residency;
|
||||
|
||||
genpd_state->power_on_latency_ns = 1000 * exit_latency;
|
||||
genpd_state->power_off_latency_ns = 1000 * entry_latency;
|
||||
genpd_state->power_on_latency_ns = 1000LL * exit_latency;
|
||||
genpd_state->power_off_latency_ns = 1000LL * entry_latency;
|
||||
genpd_state->fwnode = &state_node->fwnode;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -486,10 +486,10 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
|
||||
* and use it. Note that the event timer uses the interrupt and it's the
|
||||
* 2nd TTC hence the irq_of_parse_and_map(,1)
|
||||
*/
|
||||
timer_baseaddr = of_iomap(timer, 0);
|
||||
if (!timer_baseaddr) {
|
||||
timer_baseaddr = devm_of_iomap(&pdev->dev, timer, 0, NULL);
|
||||
if (IS_ERR(timer_baseaddr)) {
|
||||
pr_err("ERROR: invalid timer base address\n");
|
||||
return -ENXIO;
|
||||
return PTR_ERR(timer_baseaddr);
|
||||
}
|
||||
|
||||
irq = irq_of_parse_and_map(timer, 1);
|
||||
@@ -513,20 +513,27 @@ static int __init ttc_timer_probe(struct platform_device *pdev)
|
||||
clk_ce = of_clk_get(timer, clksel);
|
||||
if (IS_ERR(clk_ce)) {
|
||||
pr_err("ERROR: timer input clock not found\n");
|
||||
return PTR_ERR(clk_ce);
|
||||
ret = PTR_ERR(clk_ce);
|
||||
goto put_clk_cs;
|
||||
}
|
||||
|
||||
ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto put_clk_ce;
|
||||
|
||||
ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto put_clk_ce;
|
||||
|
||||
pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq);
|
||||
|
||||
return 0;
|
||||
|
||||
put_clk_ce:
|
||||
clk_put(clk_ce);
|
||||
put_clk_cs:
|
||||
clk_put(clk_cs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id ttc_timer_of_match[] = {
|
||||
|
||||
@@ -824,6 +824,8 @@ static ssize_t store_energy_performance_preference(
|
||||
err = cpufreq_start_governor(policy);
|
||||
if (!ret)
|
||||
ret = err;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ static int __init aic_irq_of_init(struct device_node *node,
|
||||
unsigned min_irq = JCORE_AIC2_MIN_HWIRQ;
|
||||
unsigned dom_sz = JCORE_AIC_MAX_HWIRQ+1;
|
||||
struct irq_domain *domain;
|
||||
int ret;
|
||||
|
||||
pr_info("Initializing J-Core AIC\n");
|
||||
|
||||
@@ -100,6 +101,12 @@ static int __init aic_irq_of_init(struct device_node *node,
|
||||
jcore_aic.irq_unmask = noop;
|
||||
jcore_aic.name = "AIC";
|
||||
|
||||
ret = irq_alloc_descs(-1, min_irq, dom_sz - min_irq,
|
||||
of_node_to_nid(node));
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
domain = irq_domain_add_legacy(node, dom_sz - min_irq, min_irq, min_irq,
|
||||
&jcore_aic_irqdomain_ops,
|
||||
&jcore_aic);
|
||||
|
||||
@@ -54,14 +54,7 @@ __acquires(bitmap->lock)
|
||||
{
|
||||
unsigned char *mappage;
|
||||
|
||||
if (page >= bitmap->pages) {
|
||||
/* This can happen if bitmap_start_sync goes beyond
|
||||
* End-of-device while looking for a whole page.
|
||||
* It is harmless.
|
||||
*/
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(page >= bitmap->pages);
|
||||
if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */
|
||||
return 0;
|
||||
|
||||
@@ -1365,6 +1358,14 @@ __acquires(bitmap->lock)
|
||||
sector_t csize;
|
||||
int err;
|
||||
|
||||
if (page >= bitmap->pages) {
|
||||
/*
|
||||
* This can happen if bitmap_start_sync goes beyond
|
||||
* End-of-device while looking for a whole page or
|
||||
* user set a huge number to sysfs bitmap_set_bits.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
err = md_bitmap_checkpage(bitmap, page, create, 0);
|
||||
|
||||
if (bitmap->bp[page].hijacked ||
|
||||
|
||||
@@ -3872,8 +3872,9 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale)
|
||||
static ssize_t
|
||||
safe_delay_show(struct mddev *mddev, char *page)
|
||||
{
|
||||
int msec = (mddev->safemode_delay*1000)/HZ;
|
||||
return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
|
||||
unsigned int msec = ((unsigned long)mddev->safemode_delay*1000)/HZ;
|
||||
|
||||
return sprintf(page, "%u.%03u\n", msec/1000, msec%1000);
|
||||
}
|
||||
static ssize_t
|
||||
safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
|
||||
@@ -3885,7 +3886,7 @@ safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strict_strtoul_scaled(cbuf, &msec, 3) < 0)
|
||||
if (strict_strtoul_scaled(cbuf, &msec, 3) < 0 || msec > UINT_MAX / HZ)
|
||||
return -EINVAL;
|
||||
if (msec == 0)
|
||||
mddev->safemode_delay = 0;
|
||||
@@ -4555,6 +4556,8 @@ max_corrected_read_errors_store(struct mddev *mddev, const char *buf, size_t len
|
||||
rv = kstrtouint(buf, 10, &n);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
if (n > INT_MAX)
|
||||
return -EINVAL;
|
||||
atomic_set(&mddev->max_corr_read_errors, n);
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -752,8 +752,16 @@ static struct md_rdev *read_balance(struct r10conf *conf,
|
||||
disk = r10_bio->devs[slot].devnum;
|
||||
rdev = rcu_dereference(conf->mirrors[disk].replacement);
|
||||
if (rdev == NULL || test_bit(Faulty, &rdev->flags) ||
|
||||
r10_bio->devs[slot].addr + sectors > rdev->recovery_offset)
|
||||
r10_bio->devs[slot].addr + sectors >
|
||||
rdev->recovery_offset) {
|
||||
/*
|
||||
* Read replacement first to prevent reading both rdev
|
||||
* and replacement as NULL during replacement replace
|
||||
* rdev.
|
||||
*/
|
||||
smp_mb();
|
||||
rdev = rcu_dereference(conf->mirrors[disk].rdev);
|
||||
}
|
||||
if (rdev == NULL ||
|
||||
test_bit(Faulty, &rdev->flags))
|
||||
continue;
|
||||
@@ -1449,9 +1457,15 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
|
||||
|
||||
for (i = 0; i < conf->copies; i++) {
|
||||
int d = r10_bio->devs[i].devnum;
|
||||
struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev);
|
||||
struct md_rdev *rrdev = rcu_dereference(
|
||||
conf->mirrors[d].replacement);
|
||||
struct md_rdev *rdev, *rrdev;
|
||||
|
||||
rrdev = rcu_dereference(conf->mirrors[d].replacement);
|
||||
/*
|
||||
* Read replacement first to prevent reading both rdev and
|
||||
* replacement as NULL during replacement replace rdev.
|
||||
*/
|
||||
smp_mb();
|
||||
rdev = rcu_dereference(conf->mirrors[d].rdev);
|
||||
if (rdev == rrdev)
|
||||
rrdev = NULL;
|
||||
if (rdev && (test_bit(Faulty, &rdev->flags)))
|
||||
@@ -3412,7 +3426,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
||||
int must_sync;
|
||||
int any_working;
|
||||
int need_recover = 0;
|
||||
int need_replace = 0;
|
||||
struct raid10_info *mirror = &conf->mirrors[i];
|
||||
struct md_rdev *mrdev, *mreplace;
|
||||
|
||||
@@ -3424,11 +3437,10 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
||||
!test_bit(Faulty, &mrdev->flags) &&
|
||||
!test_bit(In_sync, &mrdev->flags))
|
||||
need_recover = 1;
|
||||
if (mreplace != NULL &&
|
||||
!test_bit(Faulty, &mreplace->flags))
|
||||
need_replace = 1;
|
||||
if (mreplace && test_bit(Faulty, &mreplace->flags))
|
||||
mreplace = NULL;
|
||||
|
||||
if (!need_recover && !need_replace) {
|
||||
if (!need_recover && !mreplace) {
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
}
|
||||
@@ -3444,8 +3456,6 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
||||
rcu_read_unlock();
|
||||
continue;
|
||||
}
|
||||
if (mreplace && test_bit(Faulty, &mreplace->flags))
|
||||
mreplace = NULL;
|
||||
/* Unless we are doing a full sync, or a replacement
|
||||
* we only need to recover the block if it is set in
|
||||
* the bitmap
|
||||
@@ -3568,11 +3578,11 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr,
|
||||
bio = r10_bio->devs[1].repl_bio;
|
||||
if (bio)
|
||||
bio->bi_end_io = NULL;
|
||||
/* Note: if need_replace, then bio
|
||||
/* Note: if replace is not NULL, then bio
|
||||
* cannot be NULL as r10buf_pool_alloc will
|
||||
* have allocated it.
|
||||
*/
|
||||
if (!need_replace)
|
||||
if (!mreplace)
|
||||
break;
|
||||
bio->bi_next = biolist;
|
||||
biolist = bio;
|
||||
|
||||
@@ -44,12 +44,10 @@ static const char *tpc_names[] = {
|
||||
* memstick_debug_get_tpc_name - debug helper that returns string for
|
||||
* a TPC number
|
||||
*/
|
||||
const char *memstick_debug_get_tpc_name(int tpc)
|
||||
static __maybe_unused const char *memstick_debug_get_tpc_name(int tpc)
|
||||
{
|
||||
return tpc_names[tpc-1];
|
||||
}
|
||||
EXPORT_SYMBOL(memstick_debug_get_tpc_name);
|
||||
|
||||
|
||||
/* Read a register*/
|
||||
static inline u32 r592_read_reg(struct r592_device *dev, int address)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
#include "igc_hw.h"
|
||||
|
||||
@@ -312,6 +313,33 @@ extern char igc_driver_name[];
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
|
||||
/* RX-desc Write-Back format RSS Type's */
|
||||
enum igc_rss_type_num {
|
||||
IGC_RSS_TYPE_NO_HASH = 0,
|
||||
IGC_RSS_TYPE_HASH_TCP_IPV4 = 1,
|
||||
IGC_RSS_TYPE_HASH_IPV4 = 2,
|
||||
IGC_RSS_TYPE_HASH_TCP_IPV6 = 3,
|
||||
IGC_RSS_TYPE_HASH_IPV6_EX = 4,
|
||||
IGC_RSS_TYPE_HASH_IPV6 = 5,
|
||||
IGC_RSS_TYPE_HASH_TCP_IPV6_EX = 6,
|
||||
IGC_RSS_TYPE_HASH_UDP_IPV4 = 7,
|
||||
IGC_RSS_TYPE_HASH_UDP_IPV6 = 8,
|
||||
IGC_RSS_TYPE_HASH_UDP_IPV6_EX = 9,
|
||||
IGC_RSS_TYPE_MAX = 10,
|
||||
};
|
||||
#define IGC_RSS_TYPE_MAX_TABLE 16
|
||||
#define IGC_RSS_TYPE_MASK GENMASK(3,0) /* 4-bits (3:0) = mask 0x0F */
|
||||
|
||||
/* igc_rss_type - Rx descriptor RSS type field */
|
||||
static inline u32 igc_rss_type(const union igc_adv_rx_desc *rx_desc)
|
||||
{
|
||||
/* RSS Type 4-bits (3:0) number: 0-9 (above 9 is reserved)
|
||||
* Accessing the same bits via u16 (wb.lower.lo_dword.hs_rss.pkt_info)
|
||||
* is slightly slower than via u32 (wb.lower.lo_dword.data)
|
||||
*/
|
||||
return le32_get_bits(rx_desc->wb.lower.lo_dword.data, IGC_RSS_TYPE_MASK);
|
||||
}
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGC_START_ITR 648 /* ~6000 ints/sec */
|
||||
#define IGC_4K_ITR 980
|
||||
|
||||
@@ -1683,14 +1683,36 @@ static void igc_rx_checksum(struct igc_ring *ring,
|
||||
le32_to_cpu(rx_desc->wb.upper.status_error));
|
||||
}
|
||||
|
||||
/* Mapping HW RSS Type to enum pkt_hash_types */
|
||||
static const enum pkt_hash_types igc_rss_type_table[IGC_RSS_TYPE_MAX_TABLE] = {
|
||||
[IGC_RSS_TYPE_NO_HASH] = PKT_HASH_TYPE_L2,
|
||||
[IGC_RSS_TYPE_HASH_TCP_IPV4] = PKT_HASH_TYPE_L4,
|
||||
[IGC_RSS_TYPE_HASH_IPV4] = PKT_HASH_TYPE_L3,
|
||||
[IGC_RSS_TYPE_HASH_TCP_IPV6] = PKT_HASH_TYPE_L4,
|
||||
[IGC_RSS_TYPE_HASH_IPV6_EX] = PKT_HASH_TYPE_L3,
|
||||
[IGC_RSS_TYPE_HASH_IPV6] = PKT_HASH_TYPE_L3,
|
||||
[IGC_RSS_TYPE_HASH_TCP_IPV6_EX] = PKT_HASH_TYPE_L4,
|
||||
[IGC_RSS_TYPE_HASH_UDP_IPV4] = PKT_HASH_TYPE_L4,
|
||||
[IGC_RSS_TYPE_HASH_UDP_IPV6] = PKT_HASH_TYPE_L4,
|
||||
[IGC_RSS_TYPE_HASH_UDP_IPV6_EX] = PKT_HASH_TYPE_L4,
|
||||
[10] = PKT_HASH_TYPE_NONE, /* RSS Type above 9 "Reserved" by HW */
|
||||
[11] = PKT_HASH_TYPE_NONE, /* keep array sized for SW bit-mask */
|
||||
[12] = PKT_HASH_TYPE_NONE, /* to handle future HW revisons */
|
||||
[13] = PKT_HASH_TYPE_NONE,
|
||||
[14] = PKT_HASH_TYPE_NONE,
|
||||
[15] = PKT_HASH_TYPE_NONE,
|
||||
};
|
||||
|
||||
static inline void igc_rx_hash(struct igc_ring *ring,
|
||||
union igc_adv_rx_desc *rx_desc,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
if (ring->netdev->features & NETIF_F_RXHASH)
|
||||
skb_set_hash(skb,
|
||||
le32_to_cpu(rx_desc->wb.lower.hi_dword.rss),
|
||||
PKT_HASH_TYPE_L3);
|
||||
if (ring->netdev->features & NETIF_F_RXHASH) {
|
||||
u32 rss_hash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
|
||||
u32 rss_type = igc_rss_type(rx_desc);
|
||||
|
||||
skb_set_hash(skb, rss_hash, igc_rss_type_table[rss_type]);
|
||||
}
|
||||
}
|
||||
|
||||
static void igc_rx_vlan(struct igc_ring *rx_ring,
|
||||
@@ -6525,6 +6547,7 @@ static int igc_probe(struct pci_dev *pdev,
|
||||
netdev->features |= NETIF_F_TSO;
|
||||
netdev->features |= NETIF_F_TSO6;
|
||||
netdev->features |= NETIF_F_TSO_ECN;
|
||||
netdev->features |= NETIF_F_RXHASH;
|
||||
netdev->features |= NETIF_F_RXCSUM;
|
||||
netdev->features |= NETIF_F_HW_CSUM;
|
||||
netdev->features |= NETIF_F_SCTP_CRC;
|
||||
|
||||
@@ -1099,17 +1099,22 @@ static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue)
|
||||
{
|
||||
u32 dma_dbg_chain, dma_dbg_complete;
|
||||
u8 dcu_chain_state, dcu_complete_state;
|
||||
unsigned int dbg_reg, reg_offset;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_STATUS_READS; i++) {
|
||||
if (queue < 6)
|
||||
dma_dbg_chain = REG_READ(ah, AR_DMADBG_4);
|
||||
else
|
||||
dma_dbg_chain = REG_READ(ah, AR_DMADBG_5);
|
||||
if (queue < 6) {
|
||||
dbg_reg = AR_DMADBG_4;
|
||||
reg_offset = queue * 5;
|
||||
} else {
|
||||
dbg_reg = AR_DMADBG_5;
|
||||
reg_offset = (queue - 6) * 5;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_STATUS_READS; i++) {
|
||||
dma_dbg_chain = REG_READ(ah, dbg_reg);
|
||||
dma_dbg_complete = REG_READ(ah, AR_DMADBG_6);
|
||||
|
||||
dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f;
|
||||
dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f;
|
||||
dcu_complete_state = dma_dbg_complete & 0x3;
|
||||
|
||||
if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1))
|
||||
@@ -1128,6 +1133,7 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
|
||||
u8 dcu_chain_state, dcu_complete_state;
|
||||
bool dcu_wait_frdone = false;
|
||||
unsigned long chk_dcu = 0;
|
||||
unsigned int reg_offset;
|
||||
unsigned int i = 0;
|
||||
|
||||
dma_dbg_4 = REG_READ(ah, AR_DMADBG_4);
|
||||
@@ -1139,12 +1145,15 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
|
||||
goto exit;
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (i < 6)
|
||||
if (i < 6) {
|
||||
chk_dbg = dma_dbg_4;
|
||||
else
|
||||
reg_offset = i * 5;
|
||||
} else {
|
||||
chk_dbg = dma_dbg_5;
|
||||
reg_offset = (i - 6) * 5;
|
||||
}
|
||||
|
||||
dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f;
|
||||
dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f;
|
||||
if (dcu_chain_state == 0x6) {
|
||||
dcu_wait_frdone = true;
|
||||
chk_dcu |= BIT(i);
|
||||
|
||||
@@ -114,7 +114,13 @@ static void htc_process_conn_rsp(struct htc_target *target,
|
||||
|
||||
if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) {
|
||||
epid = svc_rspmsg->endpoint_id;
|
||||
if (epid < 0 || epid >= ENDPOINT_MAX)
|
||||
|
||||
/* Check that the received epid for the endpoint to attach
|
||||
* a new service is valid. ENDPOINT0 can't be used here as it
|
||||
* is already reserved for HTC_CTRL_RSVD_SVC service and thus
|
||||
* should not be modified.
|
||||
*/
|
||||
if (epid <= ENDPOINT0 || epid >= ENDPOINT_MAX)
|
||||
return;
|
||||
|
||||
service_id = be16_to_cpu(svc_rspmsg->service_id);
|
||||
|
||||
@@ -850,7 +850,7 @@ static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
|
||||
static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
int i;
|
||||
int i, j;
|
||||
struct ath_txq *txq;
|
||||
bool key_in_use = false;
|
||||
|
||||
@@ -868,8 +868,9 @@ static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
|
||||
int idx = txq->txq_tailidx;
|
||||
|
||||
while (!key_in_use &&
|
||||
!list_empty(&txq->txq_fifo[idx])) {
|
||||
for (j = 0; !key_in_use &&
|
||||
!list_empty(&txq->txq_fifo[idx]) &&
|
||||
j < ATH_TXFIFO_DEPTH; j++) {
|
||||
key_in_use = ath9k_txq_list_has_key(
|
||||
&txq->txq_fifo[idx], keyix);
|
||||
INCR(idx, ATH_TXFIFO_DEPTH);
|
||||
|
||||
@@ -221,6 +221,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
|
||||
if (unlikely(wmi->stopped))
|
||||
goto free_skb;
|
||||
|
||||
/* Validate the obtained SKB. */
|
||||
if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr)))
|
||||
goto free_skb;
|
||||
|
||||
hdr = (struct wmi_cmd_hdr *) skb->data;
|
||||
cmd_id = be16_to_cpu(hdr->command_id);
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ struct local_info {
|
||||
static int atmel_probe(struct pcmcia_device *p_dev)
|
||||
{
|
||||
struct local_info *local;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&p_dev->dev, "atmel_attach()\n");
|
||||
|
||||
@@ -82,8 +83,16 @@ static int atmel_probe(struct pcmcia_device *p_dev)
|
||||
|
||||
p_dev->priv = local;
|
||||
|
||||
return atmel_config(p_dev);
|
||||
} /* atmel_attach */
|
||||
ret = atmel_config(p_dev);
|
||||
if (ret)
|
||||
goto err_free_priv;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_priv:
|
||||
kfree(p_dev->priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void atmel_detach(struct pcmcia_device *link)
|
||||
{
|
||||
|
||||
@@ -1309,8 +1309,11 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
|
||||
else
|
||||
set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
|
||||
|
||||
if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
|
||||
if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) {
|
||||
local_bh_disable();
|
||||
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
|
||||
local_bh_enable();
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
@@ -1601,18 +1601,22 @@ irqreturn_t iwl_pcie_irq_rx_msix_handler(int irq, void *dev_id)
|
||||
struct msix_entry *entry = dev_id;
|
||||
struct iwl_trans_pcie *trans_pcie = iwl_pcie_get_trans_pcie(entry);
|
||||
struct iwl_trans *trans = trans_pcie->trans;
|
||||
struct iwl_rxq *rxq = &trans_pcie->rxq[entry->entry];
|
||||
struct iwl_rxq *rxq;
|
||||
|
||||
trace_iwlwifi_dev_irq_msix(trans->dev, entry, false, 0, 0);
|
||||
|
||||
if (WARN_ON(entry->entry >= trans->num_rx_queues))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (WARN_ONCE(!rxq,
|
||||
"[%d] Got MSI-X interrupt before we have Rx queues",
|
||||
entry->entry))
|
||||
if (!trans_pcie->rxq) {
|
||||
if (net_ratelimit())
|
||||
IWL_ERR(trans,
|
||||
"[%d] Got MSI-X interrupt before we have Rx queues\n",
|
||||
entry->entry);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
rxq = &trans_pcie->rxq[entry->entry];
|
||||
lock_map_acquire(&trans->sync_cmd_lockdep_map);
|
||||
IWL_DEBUG_ISR(trans, "[%d] Got interrupt\n", entry->entry);
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ orinoco_cs_probe(struct pcmcia_device *link)
|
||||
{
|
||||
struct orinoco_private *priv;
|
||||
struct orinoco_pccard *card;
|
||||
int ret;
|
||||
|
||||
priv = alloc_orinocodev(sizeof(*card), &link->dev,
|
||||
orinoco_cs_hard_reset, NULL);
|
||||
@@ -107,8 +108,16 @@ orinoco_cs_probe(struct pcmcia_device *link)
|
||||
card->p_dev = link;
|
||||
link->priv = priv;
|
||||
|
||||
return orinoco_cs_config(link);
|
||||
} /* orinoco_cs_attach */
|
||||
ret = orinoco_cs_config(link);
|
||||
if (ret)
|
||||
goto err_free_orinocodev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_orinocodev:
|
||||
free_orinocodev(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void orinoco_cs_detach(struct pcmcia_device *link)
|
||||
{
|
||||
|
||||
@@ -157,6 +157,7 @@ spectrum_cs_probe(struct pcmcia_device *link)
|
||||
{
|
||||
struct orinoco_private *priv;
|
||||
struct orinoco_pccard *card;
|
||||
int ret;
|
||||
|
||||
priv = alloc_orinocodev(sizeof(*card), &link->dev,
|
||||
spectrum_cs_hard_reset,
|
||||
@@ -169,8 +170,16 @@ spectrum_cs_probe(struct pcmcia_device *link)
|
||||
card->p_dev = link;
|
||||
link->priv = priv;
|
||||
|
||||
return spectrum_cs_config(link);
|
||||
} /* spectrum_cs_attach */
|
||||
ret = spectrum_cs_config(link);
|
||||
if (ret)
|
||||
goto err_free_orinocodev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_orinocodev:
|
||||
free_orinocodev(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void spectrum_cs_detach(struct pcmcia_device *link)
|
||||
{
|
||||
|
||||
@@ -2199,9 +2199,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
||||
|
||||
if (nd_config) {
|
||||
adapter->nd_info =
|
||||
kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
|
||||
sizeof(struct cfg80211_wowlan_nd_match *) *
|
||||
scan_rsp->number_of_sets, GFP_ATOMIC);
|
||||
kzalloc(struct_size(adapter->nd_info, matches,
|
||||
scan_rsp->number_of_sets),
|
||||
GFP_ATOMIC);
|
||||
|
||||
if (adapter->nd_info)
|
||||
adapter->nd_info->n_matches = scan_rsp->number_of_sets;
|
||||
|
||||
@@ -470,6 +470,9 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
|
||||
int rsn_ie_len = sizeof(struct element) + rsn_ie[1];
|
||||
int offset = 8;
|
||||
|
||||
param->mode_802_11i = 2;
|
||||
param->rsn_found = true;
|
||||
|
||||
/* extract RSN capabilities */
|
||||
if (offset < rsn_ie_len) {
|
||||
/* skip over pairwise suites */
|
||||
@@ -479,11 +482,8 @@ void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
|
||||
/* skip over authentication suites */
|
||||
offset += (rsn_ie[offset] * 4) + 2;
|
||||
|
||||
if (offset + 1 < rsn_ie_len) {
|
||||
param->mode_802_11i = 2;
|
||||
param->rsn_found = true;
|
||||
if (offset + 1 < rsn_ie_len)
|
||||
memcpy(param->rsn_cap, &rsn_ie[offset], 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,13 +270,14 @@ static int ray_probe(struct pcmcia_device *p_dev)
|
||||
{
|
||||
ray_dev_t *local;
|
||||
struct net_device *dev;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&p_dev->dev, "ray_attach()\n");
|
||||
|
||||
/* Allocate space for private device-specific data */
|
||||
dev = alloc_etherdev(sizeof(ray_dev_t));
|
||||
if (!dev)
|
||||
goto fail_alloc_dev;
|
||||
return -ENOMEM;
|
||||
|
||||
local = netdev_priv(dev);
|
||||
local->finder = p_dev;
|
||||
@@ -313,11 +314,16 @@ static int ray_probe(struct pcmcia_device *p_dev)
|
||||
timer_setup(&local->timer, NULL, 0);
|
||||
|
||||
this_device = p_dev;
|
||||
return ray_config(p_dev);
|
||||
ret = ray_config(p_dev);
|
||||
if (ret)
|
||||
goto err_free_dev;
|
||||
|
||||
fail_alloc_dev:
|
||||
return -ENOMEM;
|
||||
} /* ray_attach */
|
||||
return 0;
|
||||
|
||||
err_free_dev:
|
||||
free_netdev(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ray_detach(struct pcmcia_device *link)
|
||||
{
|
||||
@@ -1643,38 +1649,34 @@ static void authenticate_timeout(struct timer_list *t)
|
||||
/*===========================================================================*/
|
||||
static int parse_addr(char *in_str, UCHAR *out)
|
||||
{
|
||||
int i, k;
|
||||
int len;
|
||||
int i, j, k;
|
||||
int status;
|
||||
|
||||
if (in_str == NULL)
|
||||
return 0;
|
||||
if ((len = strlen(in_str)) < 2)
|
||||
len = strnlen(in_str, ADDRLEN * 2 + 1) - 1;
|
||||
if (len < 1)
|
||||
return 0;
|
||||
memset(out, 0, ADDRLEN);
|
||||
|
||||
status = 1;
|
||||
j = len - 1;
|
||||
if (j > 12)
|
||||
j = 12;
|
||||
i = 5;
|
||||
|
||||
while (j > 0) {
|
||||
if ((k = hex_to_bin(in_str[j--])) != -1)
|
||||
while (len > 0) {
|
||||
if ((k = hex_to_bin(in_str[len--])) != -1)
|
||||
out[i] = k;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (j == 0)
|
||||
if (len == 0)
|
||||
break;
|
||||
if ((k = hex_to_bin(in_str[j--])) != -1)
|
||||
if ((k = hex_to_bin(in_str[len--])) != -1)
|
||||
out[i] += k << 4;
|
||||
else
|
||||
return 0;
|
||||
if (!i--)
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
|
||||
@@ -1463,10 +1463,8 @@ static void rsi_shutdown(struct device *dev)
|
||||
|
||||
rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n");
|
||||
|
||||
if (hw) {
|
||||
struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config;
|
||||
|
||||
if (rsi_config_wowlan(adapter, wowlan))
|
||||
if (hw && hw->wiphy && hw->wiphy->wowlan_config) {
|
||||
if (rsi_config_wowlan(adapter, hw->wiphy->wowlan_config))
|
||||
rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n");
|
||||
}
|
||||
|
||||
@@ -1481,9 +1479,6 @@ static void rsi_shutdown(struct device *dev)
|
||||
if (sdev->write_fail)
|
||||
rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
|
||||
|
||||
if (rsi_set_sdio_pm_caps(adapter))
|
||||
rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
|
||||
|
||||
rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -1862,6 +1862,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct wl3501_card *this;
|
||||
int ret;
|
||||
|
||||
/* The io structure describes IO port mapping */
|
||||
p_dev->resource[0]->end = 16;
|
||||
@@ -1873,8 +1874,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
|
||||
|
||||
dev = alloc_etherdev(sizeof(struct wl3501_card));
|
||||
if (!dev)
|
||||
goto out_link;
|
||||
|
||||
return -ENOMEM;
|
||||
|
||||
dev->netdev_ops = &wl3501_netdev_ops;
|
||||
dev->watchdog_timeo = 5 * HZ;
|
||||
@@ -1887,9 +1887,15 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
|
||||
netif_stop_queue(dev);
|
||||
p_dev->priv = dev;
|
||||
|
||||
return wl3501_config(p_dev);
|
||||
out_link:
|
||||
return -ENOMEM;
|
||||
ret = wl3501_config(p_dev);
|
||||
if (ret)
|
||||
goto out_free_etherdev;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_etherdev:
|
||||
free_netdev(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl3501_config(struct pcmcia_device *link)
|
||||
@@ -1945,8 +1951,7 @@ static int wl3501_config(struct pcmcia_device *link)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = ((char *)&this->mac_addr)[i];
|
||||
eth_hw_addr_set(dev, this->mac_addr);
|
||||
|
||||
/* print probe information */
|
||||
printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, "
|
||||
|
||||
@@ -1571,9 +1571,10 @@ static int arm_cmn_init_dtc(struct arm_cmn *cmn, struct arm_cmn_node *dn, int id
|
||||
if (dtc->irq < 0)
|
||||
return dtc->irq;
|
||||
|
||||
writel_relaxed(0, dtc->base + CMN_DT_PMCR);
|
||||
writel_relaxed(CMN_DT_DTC_CTL_DT_EN, dtc->base + CMN_DT_DTC_CTL);
|
||||
writel_relaxed(CMN_DT_PMCR_PMU_EN | CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR);
|
||||
writeq_relaxed(0, dtc->base + CMN_DT_PMCCNTR);
|
||||
writel_relaxed(0x1ff, dtc->base + CMN_DT_PMOVSR_CLR);
|
||||
writel_relaxed(CMN_DT_PMCR_OVFL_INTR_EN, dtc->base + CMN_DT_PMCR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1629,7 +1630,7 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
|
||||
dn->type = CMN_TYPE_RNI;
|
||||
}
|
||||
|
||||
writel_relaxed(CMN_DT_DTC_CTL_DT_EN, cmn->dtc[0].base + CMN_DT_DTC_CTL);
|
||||
arm_cmn_set_state(cmn, CMN_STATE_DISABLED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@ if POWERCAP
|
||||
# Client driver configurations go here.
|
||||
config INTEL_RAPL_CORE
|
||||
tristate
|
||||
depends on PCI
|
||||
select IOSF_MBI
|
||||
|
||||
config INTEL_RAPL
|
||||
tristate "Intel RAPL Support via MSR Interface"
|
||||
depends on X86 && IOSF_MBI
|
||||
depends on X86 && PCI
|
||||
select INTEL_RAPL_CORE
|
||||
help
|
||||
This enables support for the Intel Running Average Power Limit (RAPL)
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <linux/processor.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/iosf_mbi.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/intel-family.h>
|
||||
|
||||
|
||||
@@ -1874,19 +1874,17 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
|
||||
|
||||
if (err != -EEXIST)
|
||||
regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs);
|
||||
if (!regulator->debugfs) {
|
||||
if (IS_ERR(regulator->debugfs))
|
||||
rdev_dbg(rdev, "Failed to create debugfs directory\n");
|
||||
} else {
|
||||
debugfs_create_u32("uA_load", 0444, regulator->debugfs,
|
||||
®ulator->uA_load);
|
||||
debugfs_create_u32("min_uV", 0444, regulator->debugfs,
|
||||
®ulator->voltage[PM_SUSPEND_ON].min_uV);
|
||||
debugfs_create_u32("max_uV", 0444, regulator->debugfs,
|
||||
®ulator->voltage[PM_SUSPEND_ON].max_uV);
|
||||
debugfs_create_file("constraint_flags", 0444,
|
||||
regulator->debugfs, regulator,
|
||||
&constraint_flags_fops);
|
||||
}
|
||||
|
||||
debugfs_create_u32("uA_load", 0444, regulator->debugfs,
|
||||
®ulator->uA_load);
|
||||
debugfs_create_u32("min_uV", 0444, regulator->debugfs,
|
||||
®ulator->voltage[PM_SUSPEND_ON].min_uV);
|
||||
debugfs_create_u32("max_uV", 0444, regulator->debugfs,
|
||||
®ulator->voltage[PM_SUSPEND_ON].max_uV);
|
||||
debugfs_create_file("constraint_flags", 0444, regulator->debugfs,
|
||||
regulator, &constraint_flags_fops);
|
||||
|
||||
/*
|
||||
* Check now if the regulator is an always on regulator - if
|
||||
@@ -5193,10 +5191,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
|
||||
}
|
||||
|
||||
rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
|
||||
if (IS_ERR(rdev->debugfs)) {
|
||||
rdev_warn(rdev, "Failed to create debugfs directory\n");
|
||||
return;
|
||||
}
|
||||
if (IS_ERR(rdev->debugfs))
|
||||
rdev_dbg(rdev, "Failed to create debugfs directory\n");
|
||||
|
||||
debugfs_create_u32("use_count", 0444, rdev->debugfs,
|
||||
&rdev->use_count);
|
||||
@@ -6104,7 +6100,7 @@ static int __init regulator_init(void)
|
||||
|
||||
debugfs_root = debugfs_create_dir("regulator", NULL);
|
||||
if (IS_ERR(debugfs_root))
|
||||
pr_warn("regulator: Failed to create debugfs directory\n");
|
||||
pr_debug("regulator: Failed to create debugfs directory\n");
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
|
||||
|
||||
@@ -416,7 +416,10 @@ static int dw_spi_transfer_one(struct spi_controller *master,
|
||||
int ret;
|
||||
|
||||
dws->dma_mapped = 0;
|
||||
dws->n_bytes = DIV_ROUND_UP(transfer->bits_per_word, BITS_PER_BYTE);
|
||||
dws->n_bytes =
|
||||
roundup_pow_of_two(DIV_ROUND_UP(transfer->bits_per_word,
|
||||
BITS_PER_BYTE));
|
||||
|
||||
dws->tx = (void *)transfer->tx_buf;
|
||||
dws->tx_len = transfer->len / dws->n_bytes;
|
||||
dws->rx = transfer->rx_buf;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define CS_DEMUX_OUTPUT_SEL GENMASK(3, 0)
|
||||
|
||||
#define SE_SPI_TRANS_CFG 0x25c
|
||||
#define CS_TOGGLE BIT(0)
|
||||
#define CS_TOGGLE BIT(1)
|
||||
|
||||
#define SE_SPI_WORD_LEN 0x268
|
||||
#define WORD_LEN_MSK GENMASK(9, 0)
|
||||
|
||||
@@ -319,6 +319,11 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sun8i_ths_reset_control_assert(void *data)
|
||||
{
|
||||
reset_control_assert(data);
|
||||
}
|
||||
|
||||
static int sun8i_ths_resource_init(struct ths_device *tmdev)
|
||||
{
|
||||
struct device *dev = tmdev->dev;
|
||||
@@ -339,47 +344,35 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
|
||||
if (IS_ERR(tmdev->reset))
|
||||
return PTR_ERR(tmdev->reset);
|
||||
|
||||
tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus");
|
||||
ret = reset_control_deassert(tmdev->reset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, sun8i_ths_reset_control_assert,
|
||||
tmdev->reset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tmdev->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus");
|
||||
if (IS_ERR(tmdev->bus_clk))
|
||||
return PTR_ERR(tmdev->bus_clk);
|
||||
}
|
||||
|
||||
if (tmdev->chip->has_mod_clk) {
|
||||
tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
|
||||
tmdev->mod_clk = devm_clk_get_enabled(&pdev->dev, "mod");
|
||||
if (IS_ERR(tmdev->mod_clk))
|
||||
return PTR_ERR(tmdev->mod_clk);
|
||||
}
|
||||
|
||||
ret = reset_control_deassert(tmdev->reset);
|
||||
ret = clk_set_rate(tmdev->mod_clk, 24000000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(tmdev->bus_clk);
|
||||
if (ret)
|
||||
goto assert_reset;
|
||||
|
||||
ret = clk_set_rate(tmdev->mod_clk, 24000000);
|
||||
if (ret)
|
||||
goto bus_disable;
|
||||
|
||||
ret = clk_prepare_enable(tmdev->mod_clk);
|
||||
if (ret)
|
||||
goto bus_disable;
|
||||
|
||||
ret = sun8i_ths_calibrate(tmdev);
|
||||
if (ret)
|
||||
goto mod_disable;
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
mod_disable:
|
||||
clk_disable_unprepare(tmdev->mod_clk);
|
||||
bus_disable:
|
||||
clk_disable_unprepare(tmdev->bus_clk);
|
||||
assert_reset:
|
||||
reset_control_assert(tmdev->reset);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sun8i_h3_thermal_init(struct ths_device *tmdev)
|
||||
@@ -530,17 +523,6 @@ static int sun8i_ths_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun8i_ths_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ths_device *tmdev = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(tmdev->mod_clk);
|
||||
clk_disable_unprepare(tmdev->bus_clk);
|
||||
reset_control_assert(tmdev->reset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ths_thermal_chip sun8i_a83t_ths = {
|
||||
.sensor_num = 3,
|
||||
.scale = 705,
|
||||
@@ -642,7 +624,6 @@ MODULE_DEVICE_TABLE(of, of_ths_match);
|
||||
|
||||
static struct platform_driver ths_driver = {
|
||||
.probe = sun8i_ths_probe,
|
||||
.remove = sun8i_ths_remove,
|
||||
.driver = {
|
||||
.name = "sun8i-thermal",
|
||||
.of_match_table = of_ths_match,
|
||||
|
||||
@@ -591,6 +591,8 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
|
||||
raw_spin_lock_init(&prz->buffer_lock);
|
||||
prz->flags = flags;
|
||||
prz->label = kstrdup(label, GFP_KERNEL);
|
||||
if (!prz->label)
|
||||
goto err;
|
||||
|
||||
ret = persistent_ram_buffer_map(start, size, prz, memtype);
|
||||
if (ret)
|
||||
|
||||
@@ -197,7 +197,7 @@ u64 hw_nmi_get_sample_period(int watchdog_thresh);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_HARDLOCKUP_CHECK_TIMESTAMP) && \
|
||||
defined(CONFIG_HARDLOCKUP_DETECTOR)
|
||||
defined(CONFIG_HARDLOCKUP_DETECTOR_PERF)
|
||||
void watchdog_update_hrtimer_threshold(u64 period);
|
||||
#else
|
||||
static inline void watchdog_update_hrtimer_threshold(u64 period) { }
|
||||
|
||||
@@ -265,18 +265,14 @@ void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *);
|
||||
|
||||
extern const struct pipe_buf_operations nosteal_pipe_buf_ops;
|
||||
|
||||
#ifdef CONFIG_WATCH_QUEUE
|
||||
unsigned long account_pipe_buffers(struct user_struct *user,
|
||||
unsigned long old, unsigned long new);
|
||||
bool too_many_pipe_buffers_soft(unsigned long user_bufs);
|
||||
bool too_many_pipe_buffers_hard(unsigned long user_bufs);
|
||||
bool pipe_is_unprivileged_user(void);
|
||||
#endif
|
||||
|
||||
/* for F_SETPIPE_SZ and F_GETPIPE_SZ */
|
||||
#ifdef CONFIG_WATCH_QUEUE
|
||||
int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots);
|
||||
#endif
|
||||
long pipe_fcntl(struct file *, unsigned int, unsigned long arg);
|
||||
struct pipe_inode_info *get_pipe_info(struct file *file, bool for_splice);
|
||||
|
||||
|
||||
@@ -437,7 +437,8 @@ struct nft_set_ops {
|
||||
int (*init)(const struct nft_set *set,
|
||||
const struct nft_set_desc *desc,
|
||||
const struct nlattr * const nla[]);
|
||||
void (*destroy)(const struct nft_set *set);
|
||||
void (*destroy)(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set);
|
||||
void (*gc_init)(const struct nft_set *set);
|
||||
|
||||
unsigned int elemsize;
|
||||
@@ -772,6 +773,8 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
struct nft_expr *expr_array[]);
|
||||
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
||||
bool destroy_expr);
|
||||
void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set, void *elem);
|
||||
|
||||
/**
|
||||
* struct nft_set_gc_batch_head - nf_tables set garbage collection batch
|
||||
|
||||
@@ -156,7 +156,11 @@ DEFINE_EVENT(timer_class, timer_cancel,
|
||||
{ HRTIMER_MODE_ABS_SOFT, "ABS|SOFT" }, \
|
||||
{ HRTIMER_MODE_REL_SOFT, "REL|SOFT" }, \
|
||||
{ HRTIMER_MODE_ABS_PINNED_SOFT, "ABS|PINNED|SOFT" }, \
|
||||
{ HRTIMER_MODE_REL_PINNED_SOFT, "REL|PINNED|SOFT" })
|
||||
{ HRTIMER_MODE_REL_PINNED_SOFT, "REL|PINNED|SOFT" }, \
|
||||
{ HRTIMER_MODE_ABS_HARD, "ABS|HARD" }, \
|
||||
{ HRTIMER_MODE_REL_HARD, "REL|HARD" }, \
|
||||
{ HRTIMER_MODE_ABS_PINNED_HARD, "ABS|PINNED|HARD" }, \
|
||||
{ HRTIMER_MODE_REL_PINNED_HARD, "REL|PINNED|HARD" })
|
||||
|
||||
/**
|
||||
* hrtimer_init - called when the hrtimer is initialized
|
||||
|
||||
@@ -1481,6 +1481,12 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
|
||||
ret = 1;
|
||||
} else if (ctx.optlen > max_optlen || ctx.optlen < -1) {
|
||||
/* optlen is out of bounds */
|
||||
if (*optlen > PAGE_SIZE && ctx.optlen >= 0) {
|
||||
pr_info_once("bpf setsockopt: ignoring program buffer with optlen=%d (max_optlen=%d)\n",
|
||||
ctx.optlen, max_optlen);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
ret = -EFAULT;
|
||||
} else {
|
||||
/* optlen within bounds, run kernel handler */
|
||||
@@ -1536,6 +1542,7 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
|
||||
.optname = optname,
|
||||
.retval = retval,
|
||||
};
|
||||
int orig_optlen;
|
||||
int ret;
|
||||
|
||||
/* Opportunistic check to see whether we have any BPF program
|
||||
@@ -1545,6 +1552,7 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
|
||||
if (__cgroup_bpf_prog_array_is_empty(cgrp, CGROUP_GETSOCKOPT))
|
||||
return retval;
|
||||
|
||||
orig_optlen = max_optlen;
|
||||
ctx.optlen = max_optlen;
|
||||
|
||||
max_optlen = sockopt_alloc_buf(&ctx, max_optlen, &buf);
|
||||
@@ -1568,6 +1576,7 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
orig_optlen = ctx.optlen;
|
||||
|
||||
if (copy_from_user(ctx.optval, optval,
|
||||
min(ctx.optlen, max_optlen)) != 0) {
|
||||
@@ -1587,6 +1596,12 @@ int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
|
||||
}
|
||||
|
||||
if (optval && (ctx.optlen > max_optlen || ctx.optlen < 0)) {
|
||||
if (orig_optlen > PAGE_SIZE && ctx.optlen >= 0) {
|
||||
pr_info_once("bpf getsockopt: ignoring program buffer with optlen=%d (max_optlen=%d)\n",
|
||||
ctx.optlen, max_optlen);
|
||||
ret = retval;
|
||||
goto out;
|
||||
}
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1029,6 +1029,7 @@ int crash_shrink_memory(unsigned long new_size)
|
||||
start = crashk_res.start;
|
||||
end = crashk_res.end;
|
||||
old_size = (end == 0) ? 0 : end - start + 1;
|
||||
new_size = roundup(new_size, KEXEC_CRASH_MEM_ALIGN);
|
||||
if (new_size >= old_size) {
|
||||
ret = (new_size == old_size) ? 0 : -EINVAL;
|
||||
goto unlock;
|
||||
@@ -1040,9 +1041,7 @@ int crash_shrink_memory(unsigned long new_size)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
start = roundup(start, KEXEC_CRASH_MEM_ALIGN);
|
||||
end = roundup(start + new_size, KEXEC_CRASH_MEM_ALIGN);
|
||||
|
||||
end = start + new_size;
|
||||
crash_free_reserved_phys_range(end, crashk_res.end);
|
||||
|
||||
if ((start == end) && (crashk_res.parent != NULL))
|
||||
|
||||
@@ -50,8 +50,8 @@ MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>");
|
||||
pr_alert("%s" SCALE_FLAG " %s\n", scale_type, s)
|
||||
#define VERBOSE_SCALEOUT_STRING(s) \
|
||||
do { if (verbose) pr_alert("%s" SCALE_FLAG " %s\n", scale_type, s); } while (0)
|
||||
#define VERBOSE_SCALEOUT_ERRSTRING(s) \
|
||||
do { if (verbose) pr_alert("%s" SCALE_FLAG "!!! %s\n", scale_type, s); } while (0)
|
||||
#define SCALEOUT_ERRSTRING(s) \
|
||||
pr_alert("%s" SCALE_FLAG "!!! %s\n", scale_type, s)
|
||||
|
||||
/*
|
||||
* The intended use cases for the nreaders and nwriters module parameters
|
||||
@@ -500,89 +500,6 @@ rcu_scale_print_module_parms(struct rcu_scale_ops *cur_ops, const char *tag)
|
||||
scale_type, tag, nrealreaders, nrealwriters, verbose, shutdown);
|
||||
}
|
||||
|
||||
static void
|
||||
rcu_scale_cleanup(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int ngps = 0;
|
||||
u64 *wdp;
|
||||
u64 *wdpp;
|
||||
|
||||
/*
|
||||
* Would like warning at start, but everything is expedited
|
||||
* during the mid-boot phase, so have to wait till the end.
|
||||
*/
|
||||
if (rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp)
|
||||
VERBOSE_SCALEOUT_ERRSTRING("All grace periods expedited, no normal ones to measure!");
|
||||
if (rcu_gp_is_normal() && gp_exp)
|
||||
VERBOSE_SCALEOUT_ERRSTRING("All grace periods normal, no expedited ones to measure!");
|
||||
if (gp_exp && gp_async)
|
||||
VERBOSE_SCALEOUT_ERRSTRING("No expedited async GPs, so went with async!");
|
||||
|
||||
if (torture_cleanup_begin())
|
||||
return;
|
||||
if (!cur_ops) {
|
||||
torture_cleanup_end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reader_tasks) {
|
||||
for (i = 0; i < nrealreaders; i++)
|
||||
torture_stop_kthread(rcu_scale_reader,
|
||||
reader_tasks[i]);
|
||||
kfree(reader_tasks);
|
||||
}
|
||||
|
||||
if (writer_tasks) {
|
||||
for (i = 0; i < nrealwriters; i++) {
|
||||
torture_stop_kthread(rcu_scale_writer,
|
||||
writer_tasks[i]);
|
||||
if (!writer_n_durations)
|
||||
continue;
|
||||
j = writer_n_durations[i];
|
||||
pr_alert("%s%s writer %d gps: %d\n",
|
||||
scale_type, SCALE_FLAG, i, j);
|
||||
ngps += j;
|
||||
}
|
||||
pr_alert("%s%s start: %llu end: %llu duration: %llu gps: %d batches: %ld\n",
|
||||
scale_type, SCALE_FLAG,
|
||||
t_rcu_scale_writer_started, t_rcu_scale_writer_finished,
|
||||
t_rcu_scale_writer_finished -
|
||||
t_rcu_scale_writer_started,
|
||||
ngps,
|
||||
rcuscale_seq_diff(b_rcu_gp_test_finished,
|
||||
b_rcu_gp_test_started));
|
||||
for (i = 0; i < nrealwriters; i++) {
|
||||
if (!writer_durations)
|
||||
break;
|
||||
if (!writer_n_durations)
|
||||
continue;
|
||||
wdpp = writer_durations[i];
|
||||
if (!wdpp)
|
||||
continue;
|
||||
for (j = 0; j < writer_n_durations[i]; j++) {
|
||||
wdp = &wdpp[j];
|
||||
pr_alert("%s%s %4d writer-duration: %5d %llu\n",
|
||||
scale_type, SCALE_FLAG,
|
||||
i, j, *wdp);
|
||||
if (j % 100 == 0)
|
||||
schedule_timeout_uninterruptible(1);
|
||||
}
|
||||
kfree(writer_durations[i]);
|
||||
}
|
||||
kfree(writer_tasks);
|
||||
kfree(writer_durations);
|
||||
kfree(writer_n_durations);
|
||||
}
|
||||
|
||||
/* Do torture-type-specific cleanup operations. */
|
||||
if (cur_ops->cleanup != NULL)
|
||||
cur_ops->cleanup();
|
||||
|
||||
torture_cleanup_end();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number if non-negative. If -1, the number of CPUs.
|
||||
* If less than -1, that much less than the number of CPUs, but
|
||||
@@ -602,21 +519,6 @@ static int compute_real(int n)
|
||||
return nr;
|
||||
}
|
||||
|
||||
/*
|
||||
* RCU scalability shutdown kthread. Just waits to be awakened, then shuts
|
||||
* down system.
|
||||
*/
|
||||
static int
|
||||
rcu_scale_shutdown(void *arg)
|
||||
{
|
||||
wait_event(shutdown_wq,
|
||||
atomic_read(&n_rcu_scale_writer_finished) >= nrealwriters);
|
||||
smp_mb(); /* Wake before output. */
|
||||
rcu_scale_cleanup();
|
||||
kernel_power_off();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* kfree_rcu() scalability tests: Start a kfree_rcu() loop on all CPUs for number
|
||||
* of iterations and measure total time and number of GP for all iterations to complete.
|
||||
@@ -736,8 +638,8 @@ kfree_scale_cleanup(void)
|
||||
static int
|
||||
kfree_scale_shutdown(void *arg)
|
||||
{
|
||||
wait_event(shutdown_wq,
|
||||
atomic_read(&n_kfree_scale_thread_ended) >= kfree_nrealthreads);
|
||||
wait_event_idle(shutdown_wq,
|
||||
atomic_read(&n_kfree_scale_thread_ended) >= kfree_nrealthreads);
|
||||
|
||||
smp_mb(); /* Wake before output. */
|
||||
|
||||
@@ -791,6 +693,108 @@ unwind:
|
||||
return firsterr;
|
||||
}
|
||||
|
||||
static void
|
||||
rcu_scale_cleanup(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int ngps = 0;
|
||||
u64 *wdp;
|
||||
u64 *wdpp;
|
||||
|
||||
/*
|
||||
* Would like warning at start, but everything is expedited
|
||||
* during the mid-boot phase, so have to wait till the end.
|
||||
*/
|
||||
if (rcu_gp_is_expedited() && !rcu_gp_is_normal() && !gp_exp)
|
||||
SCALEOUT_ERRSTRING("All grace periods expedited, no normal ones to measure!");
|
||||
if (rcu_gp_is_normal() && gp_exp)
|
||||
SCALEOUT_ERRSTRING("All grace periods normal, no expedited ones to measure!");
|
||||
if (gp_exp && gp_async)
|
||||
SCALEOUT_ERRSTRING("No expedited async GPs, so went with async!");
|
||||
|
||||
if (kfree_rcu_test) {
|
||||
kfree_scale_cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (torture_cleanup_begin())
|
||||
return;
|
||||
if (!cur_ops) {
|
||||
torture_cleanup_end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reader_tasks) {
|
||||
for (i = 0; i < nrealreaders; i++)
|
||||
torture_stop_kthread(rcu_scale_reader,
|
||||
reader_tasks[i]);
|
||||
kfree(reader_tasks);
|
||||
}
|
||||
|
||||
if (writer_tasks) {
|
||||
for (i = 0; i < nrealwriters; i++) {
|
||||
torture_stop_kthread(rcu_scale_writer,
|
||||
writer_tasks[i]);
|
||||
if (!writer_n_durations)
|
||||
continue;
|
||||
j = writer_n_durations[i];
|
||||
pr_alert("%s%s writer %d gps: %d\n",
|
||||
scale_type, SCALE_FLAG, i, j);
|
||||
ngps += j;
|
||||
}
|
||||
pr_alert("%s%s start: %llu end: %llu duration: %llu gps: %d batches: %ld\n",
|
||||
scale_type, SCALE_FLAG,
|
||||
t_rcu_scale_writer_started, t_rcu_scale_writer_finished,
|
||||
t_rcu_scale_writer_finished -
|
||||
t_rcu_scale_writer_started,
|
||||
ngps,
|
||||
rcuscale_seq_diff(b_rcu_gp_test_finished,
|
||||
b_rcu_gp_test_started));
|
||||
for (i = 0; i < nrealwriters; i++) {
|
||||
if (!writer_durations)
|
||||
break;
|
||||
if (!writer_n_durations)
|
||||
continue;
|
||||
wdpp = writer_durations[i];
|
||||
if (!wdpp)
|
||||
continue;
|
||||
for (j = 0; j < writer_n_durations[i]; j++) {
|
||||
wdp = &wdpp[j];
|
||||
pr_alert("%s%s %4d writer-duration: %5d %llu\n",
|
||||
scale_type, SCALE_FLAG,
|
||||
i, j, *wdp);
|
||||
if (j % 100 == 0)
|
||||
schedule_timeout_uninterruptible(1);
|
||||
}
|
||||
kfree(writer_durations[i]);
|
||||
}
|
||||
kfree(writer_tasks);
|
||||
kfree(writer_durations);
|
||||
kfree(writer_n_durations);
|
||||
}
|
||||
|
||||
/* Do torture-type-specific cleanup operations. */
|
||||
if (cur_ops->cleanup != NULL)
|
||||
cur_ops->cleanup();
|
||||
|
||||
torture_cleanup_end();
|
||||
}
|
||||
|
||||
/*
|
||||
* RCU scalability shutdown kthread. Just waits to be awakened, then shuts
|
||||
* down system.
|
||||
*/
|
||||
static int
|
||||
rcu_scale_shutdown(void *arg)
|
||||
{
|
||||
wait_event_idle(shutdown_wq, atomic_read(&n_rcu_scale_writer_finished) >= nrealwriters);
|
||||
smp_mb(); /* Wake before output. */
|
||||
rcu_scale_cleanup();
|
||||
kernel_power_off();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int __init
|
||||
rcu_scale_init(void)
|
||||
{
|
||||
@@ -845,7 +849,7 @@ rcu_scale_init(void)
|
||||
reader_tasks = kcalloc(nrealreaders, sizeof(reader_tasks[0]),
|
||||
GFP_KERNEL);
|
||||
if (reader_tasks == NULL) {
|
||||
VERBOSE_SCALEOUT_ERRSTRING("out of memory");
|
||||
SCALEOUT_ERRSTRING("out of memory");
|
||||
firsterr = -ENOMEM;
|
||||
goto unwind;
|
||||
}
|
||||
@@ -865,7 +869,7 @@ rcu_scale_init(void)
|
||||
kcalloc(nrealwriters, sizeof(*writer_n_durations),
|
||||
GFP_KERNEL);
|
||||
if (!writer_tasks || !writer_durations || !writer_n_durations) {
|
||||
VERBOSE_SCALEOUT_ERRSTRING("out of memory");
|
||||
SCALEOUT_ERRSTRING("out of memory");
|
||||
firsterr = -ENOMEM;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
@@ -1037,27 +1037,52 @@ retry_delete:
|
||||
}
|
||||
|
||||
/*
|
||||
* return timer owned by the process, used by exit_itimers
|
||||
* Delete a timer if it is armed, remove it from the hash and schedule it
|
||||
* for RCU freeing.
|
||||
*/
|
||||
static void itimer_delete(struct k_itimer *timer)
|
||||
{
|
||||
retry_delete:
|
||||
spin_lock_irq(&timer->it_lock);
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* irqsave is required to make timer_wait_running() work.
|
||||
*/
|
||||
spin_lock_irqsave(&timer->it_lock, flags);
|
||||
|
||||
retry_delete:
|
||||
/*
|
||||
* Even if the timer is not longer accessible from other tasks
|
||||
* it still might be armed and queued in the underlying timer
|
||||
* mechanism. Worse, that timer mechanism might run the expiry
|
||||
* function concurrently.
|
||||
*/
|
||||
if (timer_delete_hook(timer) == TIMER_RETRY) {
|
||||
spin_unlock_irq(&timer->it_lock);
|
||||
/*
|
||||
* Timer is expired concurrently, prevent livelocks
|
||||
* and pointless spinning on RT.
|
||||
*
|
||||
* timer_wait_running() drops timer::it_lock, which opens
|
||||
* the possibility for another task to delete the timer.
|
||||
*
|
||||
* That's not possible here because this is invoked from
|
||||
* do_exit() only for the last thread of the thread group.
|
||||
* So no other task can access and delete that timer.
|
||||
*/
|
||||
if (WARN_ON_ONCE(timer_wait_running(timer, &flags) != timer))
|
||||
return;
|
||||
|
||||
goto retry_delete;
|
||||
}
|
||||
list_del(&timer->list);
|
||||
|
||||
spin_unlock_irq(&timer->it_lock);
|
||||
spin_unlock_irqrestore(&timer->it_lock, flags);
|
||||
release_posix_timer(timer, IT_ID_SET);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called by do_exit or de_thread, only when nobody else can
|
||||
* modify the signal->posix_timers list. Yet we need sighand->siglock
|
||||
* to prevent the race with /proc/pid/timers.
|
||||
* Invoked from do_exit() when the last thread of a thread group exits.
|
||||
* At that point no other task can access the timers of the dying
|
||||
* task anymore.
|
||||
*/
|
||||
void exit_itimers(struct task_struct *tsk)
|
||||
{
|
||||
@@ -1067,10 +1092,12 @@ void exit_itimers(struct task_struct *tsk)
|
||||
if (list_empty(&tsk->signal->posix_timers))
|
||||
return;
|
||||
|
||||
/* Protect against concurrent read via /proc/$PID/timers */
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
list_replace_init(&tsk->signal->posix_timers, &timers);
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
|
||||
/* The timers are not longer accessible via tsk::signal */
|
||||
while (!list_empty(&timers)) {
|
||||
tmr = list_first_entry(&timers, struct k_itimer, list);
|
||||
itimer_delete(tmr);
|
||||
|
||||
@@ -114,14 +114,14 @@ static void watchdog_overflow_callback(struct perf_event *event,
|
||||
/* Ensure the watchdog never gets throttled */
|
||||
event->hw.interrupts = 0;
|
||||
|
||||
if (!watchdog_check_timestamp())
|
||||
return;
|
||||
|
||||
if (__this_cpu_read(watchdog_nmi_touch) == true) {
|
||||
__this_cpu_write(watchdog_nmi_touch, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!watchdog_check_timestamp())
|
||||
return;
|
||||
|
||||
/* check for a hardlockup
|
||||
* This is done by making sure our timer interrupt
|
||||
* is incrementing. The timer interrupt should have
|
||||
|
||||
@@ -922,24 +922,27 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev,
|
||||
nla_total_size(sizeof(struct ifla_vf_rate)) +
|
||||
nla_total_size(sizeof(struct ifla_vf_link_state)) +
|
||||
nla_total_size(sizeof(struct ifla_vf_rss_query_en)) +
|
||||
nla_total_size(0) + /* nest IFLA_VF_STATS */
|
||||
/* IFLA_VF_STATS_RX_PACKETS */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_TX_PACKETS */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_RX_BYTES */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_TX_BYTES */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_BROADCAST */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_MULTICAST */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_RX_DROPPED */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_TX_DROPPED */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
nla_total_size(sizeof(struct ifla_vf_trust)));
|
||||
if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS) {
|
||||
size += num_vfs *
|
||||
(nla_total_size(0) + /* nest IFLA_VF_STATS */
|
||||
/* IFLA_VF_STATS_RX_PACKETS */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_TX_PACKETS */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_RX_BYTES */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_TX_BYTES */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_BROADCAST */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_MULTICAST */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_RX_DROPPED */
|
||||
nla_total_size_64bit(sizeof(__u64)) +
|
||||
/* IFLA_VF_STATS_TX_DROPPED */
|
||||
nla_total_size_64bit(sizeof(__u64)));
|
||||
}
|
||||
return size;
|
||||
} else
|
||||
return 0;
|
||||
@@ -1214,7 +1217,8 @@ static noinline_for_stack int rtnl_fill_stats(struct sk_buff *skb,
|
||||
static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
int vfs_num,
|
||||
struct nlattr *vfinfo)
|
||||
struct nlattr *vfinfo,
|
||||
u32 ext_filter_mask)
|
||||
{
|
||||
struct ifla_vf_rss_query_en vf_rss_query_en;
|
||||
struct nlattr *vf, *vfstats, *vfvlanlist;
|
||||
@@ -1320,33 +1324,35 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
|
||||
goto nla_put_vf_failure;
|
||||
}
|
||||
nla_nest_end(skb, vfvlanlist);
|
||||
memset(&vf_stats, 0, sizeof(vf_stats));
|
||||
if (dev->netdev_ops->ndo_get_vf_stats)
|
||||
dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num,
|
||||
&vf_stats);
|
||||
vfstats = nla_nest_start_noflag(skb, IFLA_VF_STATS);
|
||||
if (!vfstats)
|
||||
goto nla_put_vf_failure;
|
||||
if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS,
|
||||
vf_stats.rx_packets, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS,
|
||||
vf_stats.tx_packets, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES,
|
||||
vf_stats.rx_bytes, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES,
|
||||
vf_stats.tx_bytes, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST,
|
||||
vf_stats.broadcast, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST,
|
||||
vf_stats.multicast, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_DROPPED,
|
||||
vf_stats.rx_dropped, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_DROPPED,
|
||||
vf_stats.tx_dropped, IFLA_VF_STATS_PAD)) {
|
||||
nla_nest_cancel(skb, vfstats);
|
||||
goto nla_put_vf_failure;
|
||||
if (~ext_filter_mask & RTEXT_FILTER_SKIP_STATS) {
|
||||
memset(&vf_stats, 0, sizeof(vf_stats));
|
||||
if (dev->netdev_ops->ndo_get_vf_stats)
|
||||
dev->netdev_ops->ndo_get_vf_stats(dev, vfs_num,
|
||||
&vf_stats);
|
||||
vfstats = nla_nest_start_noflag(skb, IFLA_VF_STATS);
|
||||
if (!vfstats)
|
||||
goto nla_put_vf_failure;
|
||||
if (nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_PACKETS,
|
||||
vf_stats.rx_packets, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_PACKETS,
|
||||
vf_stats.tx_packets, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_BYTES,
|
||||
vf_stats.rx_bytes, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_BYTES,
|
||||
vf_stats.tx_bytes, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_BROADCAST,
|
||||
vf_stats.broadcast, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_MULTICAST,
|
||||
vf_stats.multicast, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_RX_DROPPED,
|
||||
vf_stats.rx_dropped, IFLA_VF_STATS_PAD) ||
|
||||
nla_put_u64_64bit(skb, IFLA_VF_STATS_TX_DROPPED,
|
||||
vf_stats.tx_dropped, IFLA_VF_STATS_PAD)) {
|
||||
nla_nest_cancel(skb, vfstats);
|
||||
goto nla_put_vf_failure;
|
||||
}
|
||||
nla_nest_end(skb, vfstats);
|
||||
}
|
||||
nla_nest_end(skb, vfstats);
|
||||
nla_nest_end(skb, vf);
|
||||
return 0;
|
||||
|
||||
@@ -1379,7 +1385,7 @@ static noinline_for_stack int rtnl_fill_vf(struct sk_buff *skb,
|
||||
return -EMSGSIZE;
|
||||
|
||||
for (i = 0; i < num_vfs; i++) {
|
||||
if (rtnl_fill_vfinfo(skb, dev, i, vfinfo))
|
||||
if (rtnl_fill_vfinfo(skb, dev, i, vfinfo, ext_filter_mask))
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
|
||||
@@ -581,6 +581,58 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
|
||||
return __nft_trans_set_add(ctx, msg_type, set, NULL);
|
||||
}
|
||||
|
||||
static void nft_setelem_data_deactivate(const struct net *net,
|
||||
const struct nft_set *set,
|
||||
struct nft_set_elem *elem);
|
||||
|
||||
static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
|
||||
struct nft_set *set,
|
||||
const struct nft_set_iter *iter,
|
||||
struct nft_set_elem *elem)
|
||||
{
|
||||
nft_setelem_data_deactivate(ctx->net, set, elem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nft_set_elem_catchall {
|
||||
struct list_head list;
|
||||
struct rcu_head rcu;
|
||||
void *elem;
|
||||
};
|
||||
|
||||
static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
|
||||
struct nft_set *set)
|
||||
{
|
||||
u8 genmask = nft_genmask_next(ctx->net);
|
||||
struct nft_set_elem_catchall *catchall;
|
||||
struct nft_set_elem elem;
|
||||
struct nft_set_ext *ext;
|
||||
|
||||
list_for_each_entry(catchall, &set->catchall_list, list) {
|
||||
ext = nft_set_elem_ext(set, catchall->elem);
|
||||
if (!nft_set_elem_active(ext, genmask))
|
||||
continue;
|
||||
|
||||
elem.priv = catchall->elem;
|
||||
nft_setelem_data_deactivate(ctx->net, set, &elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
struct nft_set_iter iter = {
|
||||
.genmask = nft_genmask_next(ctx->net),
|
||||
.fn = nft_mapelem_deactivate,
|
||||
};
|
||||
|
||||
set->ops->walk(ctx, set, &iter);
|
||||
WARN_ON_ONCE(iter.err);
|
||||
|
||||
nft_map_catchall_deactivate(ctx, set);
|
||||
}
|
||||
|
||||
static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
int err;
|
||||
@@ -589,6 +641,9 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_deactivate(ctx, set);
|
||||
|
||||
nft_deactivate_next(ctx->net, set);
|
||||
ctx->table->use--;
|
||||
|
||||
@@ -3407,12 +3462,6 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nft_set_elem_catchall {
|
||||
struct list_head list;
|
||||
struct rcu_head rcu;
|
||||
void *elem;
|
||||
};
|
||||
|
||||
int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
u8 genmask = nft_genmask_next(ctx->net);
|
||||
@@ -4734,7 +4783,7 @@ err_set_expr_alloc:
|
||||
for (i = 0; i < set->num_exprs; i++)
|
||||
nft_expr_destroy(&ctx, set->exprs[i]);
|
||||
err_set_destroy:
|
||||
ops->destroy(set);
|
||||
ops->destroy(&ctx, set);
|
||||
err_set_init:
|
||||
kfree(set->name);
|
||||
err_set_name:
|
||||
@@ -4749,7 +4798,7 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
|
||||
|
||||
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
|
||||
list_del_rcu(&catchall->list);
|
||||
nft_set_elem_destroy(set, catchall->elem, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, catchall->elem);
|
||||
kfree_rcu(catchall, rcu);
|
||||
}
|
||||
}
|
||||
@@ -4764,7 +4813,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
for (i = 0; i < set->num_exprs; i++)
|
||||
nft_expr_destroy(ctx, set->exprs[i]);
|
||||
|
||||
set->ops->destroy(set);
|
||||
set->ops->destroy(ctx, set);
|
||||
nft_set_catchall_destroy(ctx, set);
|
||||
kfree(set->name);
|
||||
kvfree(set);
|
||||
@@ -4925,10 +4974,60 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
}
|
||||
}
|
||||
|
||||
static void nft_setelem_data_activate(const struct net *net,
|
||||
const struct nft_set *set,
|
||||
struct nft_set_elem *elem);
|
||||
|
||||
static int nft_mapelem_activate(const struct nft_ctx *ctx,
|
||||
struct nft_set *set,
|
||||
const struct nft_set_iter *iter,
|
||||
struct nft_set_elem *elem)
|
||||
{
|
||||
nft_setelem_data_activate(ctx->net, set, elem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nft_map_catchall_activate(const struct nft_ctx *ctx,
|
||||
struct nft_set *set)
|
||||
{
|
||||
u8 genmask = nft_genmask_next(ctx->net);
|
||||
struct nft_set_elem_catchall *catchall;
|
||||
struct nft_set_elem elem;
|
||||
struct nft_set_ext *ext;
|
||||
|
||||
list_for_each_entry(catchall, &set->catchall_list, list) {
|
||||
ext = nft_set_elem_ext(set, catchall->elem);
|
||||
if (!nft_set_elem_active(ext, genmask))
|
||||
continue;
|
||||
|
||||
elem.priv = catchall->elem;
|
||||
nft_setelem_data_activate(ctx->net, set, &elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
struct nft_set_iter iter = {
|
||||
.genmask = nft_genmask_next(ctx->net),
|
||||
.fn = nft_mapelem_activate,
|
||||
};
|
||||
|
||||
set->ops->walk(ctx, set, &iter);
|
||||
WARN_ON_ONCE(iter.err);
|
||||
|
||||
nft_map_catchall_activate(ctx, set);
|
||||
}
|
||||
|
||||
void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set)
|
||||
{
|
||||
if (nft_set_is_anonymous(set))
|
||||
if (nft_set_is_anonymous(set)) {
|
||||
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_activate(ctx, set);
|
||||
|
||||
nft_clear(ctx->net, set);
|
||||
}
|
||||
|
||||
set->use++;
|
||||
}
|
||||
@@ -4947,13 +5046,20 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
set->use--;
|
||||
break;
|
||||
case NFT_TRANS_PREPARE:
|
||||
if (nft_set_is_anonymous(set))
|
||||
nft_deactivate_next(ctx->net, set);
|
||||
if (nft_set_is_anonymous(set)) {
|
||||
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_deactivate(ctx, set);
|
||||
|
||||
nft_deactivate_next(ctx->net, set);
|
||||
}
|
||||
set->use--;
|
||||
return;
|
||||
case NFT_TRANS_ABORT:
|
||||
case NFT_TRANS_RELEASE:
|
||||
if (nft_set_is_anonymous(set) &&
|
||||
set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_deactivate(ctx, set);
|
||||
|
||||
set->use--;
|
||||
fallthrough;
|
||||
default:
|
||||
@@ -5669,6 +5775,7 @@ static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
|
||||
__nft_set_elem_expr_destroy(ctx, expr);
|
||||
}
|
||||
|
||||
/* Drop references and destroy. Called from gc, dynset and abort path. */
|
||||
void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
||||
bool destroy_expr)
|
||||
{
|
||||
@@ -5690,11 +5797,11 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
|
||||
|
||||
/* Only called from commit path, nft_setelem_data_deactivate() already deals
|
||||
* with the refcounting from the preparation phase.
|
||||
/* Destroy element. References have been already dropped in the preparation
|
||||
* path via nft_setelem_data_deactivate().
|
||||
*/
|
||||
static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set, void *elem)
|
||||
void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set, void *elem)
|
||||
{
|
||||
struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
|
||||
|
||||
@@ -9323,6 +9430,9 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
|
||||
case NFT_MSG_DELSET:
|
||||
trans->ctx.table->use++;
|
||||
nft_clear(trans->ctx.net, nft_trans_set(trans));
|
||||
if (nft_trans_set(trans)->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_activate(&trans->ctx, nft_trans_set(trans));
|
||||
|
||||
nft_trans_destroy(trans);
|
||||
break;
|
||||
case NFT_MSG_NEWSETELEM:
|
||||
@@ -10089,6 +10199,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
|
||||
list_for_each_entry_safe(set, ns, &table->sets, list) {
|
||||
list_del(&set->list);
|
||||
table->use--;
|
||||
if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
|
||||
nft_map_deactivate(&ctx, set);
|
||||
|
||||
nft_set_destroy(&ctx, set);
|
||||
}
|
||||
list_for_each_entry_safe(obj, ne, &table->objects, list) {
|
||||
|
||||
@@ -271,13 +271,14 @@ static int nft_bitmap_init(const struct nft_set *set,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nft_bitmap_destroy(const struct nft_set *set)
|
||||
static void nft_bitmap_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_bitmap *priv = nft_set_priv(set);
|
||||
struct nft_bitmap_elem *be, *n;
|
||||
|
||||
list_for_each_entry_safe(be, n, &priv->list, head)
|
||||
nft_set_elem_destroy(set, be, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, be);
|
||||
}
|
||||
|
||||
static bool nft_bitmap_estimate(const struct nft_set_desc *desc, u32 features,
|
||||
|
||||
@@ -400,19 +400,31 @@ static int nft_rhash_init(const struct nft_set *set,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nft_rhash_ctx {
|
||||
const struct nft_ctx ctx;
|
||||
const struct nft_set *set;
|
||||
};
|
||||
|
||||
static void nft_rhash_elem_destroy(void *ptr, void *arg)
|
||||
{
|
||||
nft_set_elem_destroy(arg, ptr, true);
|
||||
struct nft_rhash_ctx *rhash_ctx = arg;
|
||||
|
||||
nf_tables_set_elem_destroy(&rhash_ctx->ctx, rhash_ctx->set, ptr);
|
||||
}
|
||||
|
||||
static void nft_rhash_destroy(const struct nft_set *set)
|
||||
static void nft_rhash_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_rhash *priv = nft_set_priv(set);
|
||||
struct nft_rhash_ctx rhash_ctx = {
|
||||
.ctx = *ctx,
|
||||
.set = set,
|
||||
};
|
||||
|
||||
cancel_delayed_work_sync(&priv->gc_work);
|
||||
rcu_barrier();
|
||||
rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
|
||||
(void *)set);
|
||||
(void *)&rhash_ctx);
|
||||
}
|
||||
|
||||
/* Number of buckets is stored in u32, so cap our result to 1U<<31 */
|
||||
@@ -643,7 +655,8 @@ static int nft_hash_init(const struct nft_set *set,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nft_hash_destroy(const struct nft_set *set)
|
||||
static void nft_hash_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_hash *priv = nft_set_priv(set);
|
||||
struct nft_hash_elem *he;
|
||||
@@ -653,7 +666,7 @@ static void nft_hash_destroy(const struct nft_set *set)
|
||||
for (i = 0; i < priv->buckets; i++) {
|
||||
hlist_for_each_entry_safe(he, next, &priv->table[i], node) {
|
||||
hlist_del_rcu(&he->node);
|
||||
nft_set_elem_destroy(set, he, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, he);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2152,10 +2152,12 @@ out_scratch:
|
||||
|
||||
/**
|
||||
* nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
|
||||
* @ctx: context
|
||||
* @set: nftables API set representation
|
||||
* @m: matching data pointing to key mapping array
|
||||
*/
|
||||
static void nft_set_pipapo_match_destroy(const struct nft_set *set,
|
||||
static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set,
|
||||
struct nft_pipapo_match *m)
|
||||
{
|
||||
struct nft_pipapo_field *f;
|
||||
@@ -2172,15 +2174,17 @@ static void nft_set_pipapo_match_destroy(const struct nft_set *set,
|
||||
|
||||
e = f->mt[r].e;
|
||||
|
||||
nft_set_elem_destroy(set, e, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nft_pipapo_destroy() - Free private data for set and all committed elements
|
||||
* @ctx: context
|
||||
* @set: nftables API set representation
|
||||
*/
|
||||
static void nft_pipapo_destroy(const struct nft_set *set)
|
||||
static void nft_pipapo_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_pipapo *priv = nft_set_priv(set);
|
||||
struct nft_pipapo_match *m;
|
||||
@@ -2190,7 +2194,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
|
||||
if (m) {
|
||||
rcu_barrier();
|
||||
|
||||
nft_set_pipapo_match_destroy(set, m);
|
||||
nft_set_pipapo_match_destroy(ctx, set, m);
|
||||
|
||||
#ifdef NFT_PIPAPO_ALIGN
|
||||
free_percpu(m->scratch_aligned);
|
||||
@@ -2207,7 +2211,7 @@ static void nft_pipapo_destroy(const struct nft_set *set)
|
||||
m = priv->clone;
|
||||
|
||||
if (priv->dirty)
|
||||
nft_set_pipapo_match_destroy(set, m);
|
||||
nft_set_pipapo_match_destroy(ctx, set, m);
|
||||
|
||||
#ifdef NFT_PIPAPO_ALIGN
|
||||
free_percpu(priv->clone->scratch_aligned);
|
||||
|
||||
@@ -664,7 +664,8 @@ static int nft_rbtree_init(const struct nft_set *set,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nft_rbtree_destroy(const struct nft_set *set)
|
||||
static void nft_rbtree_destroy(const struct nft_ctx *ctx,
|
||||
const struct nft_set *set)
|
||||
{
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
struct nft_rbtree_elem *rbe;
|
||||
@@ -675,7 +676,7 @@ static void nft_rbtree_destroy(const struct nft_set *set)
|
||||
while ((node = priv->root.rb_node) != NULL) {
|
||||
rb_erase(node, &priv->root);
|
||||
rbe = rb_entry(node, struct nft_rbtree_elem, node);
|
||||
nft_set_elem_destroy(set, rbe, true);
|
||||
nf_tables_set_elem_destroy(ctx, set, rbe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -394,7 +394,8 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
|
||||
const u8 *service_name_tlv = NULL;
|
||||
const u8 *miux_tlv = NULL;
|
||||
const u8 *rw_tlv = NULL;
|
||||
u8 service_name_tlv_length, miux_tlv_length, rw_tlv_length, rw;
|
||||
u8 service_name_tlv_length = 0;
|
||||
u8 miux_tlv_length, rw_tlv_length, rw;
|
||||
int err;
|
||||
u16 size = 0;
|
||||
__be16 miux;
|
||||
|
||||
@@ -8292,6 +8292,22 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool sctp_bpf_bypass_getsockopt(int level, int optname)
|
||||
{
|
||||
if (level == SOL_SCTP) {
|
||||
switch (optname) {
|
||||
case SCTP_SOCKOPT_PEELOFF:
|
||||
case SCTP_SOCKOPT_PEELOFF_FLAGS:
|
||||
case SCTP_SOCKOPT_CONNECTX3:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int sctp_hash(struct sock *sk)
|
||||
{
|
||||
/* STUB */
|
||||
@@ -9660,6 +9676,7 @@ struct proto sctp_prot = {
|
||||
.shutdown = sctp_shutdown,
|
||||
.setsockopt = sctp_setsockopt,
|
||||
.getsockopt = sctp_getsockopt,
|
||||
.bpf_bypass_getsockopt = sctp_bpf_bypass_getsockopt,
|
||||
.sendmsg = sctp_sendmsg,
|
||||
.recvmsg = sctp_recvmsg,
|
||||
.bind = sctp_bind,
|
||||
@@ -9712,6 +9729,7 @@ struct proto sctpv6_prot = {
|
||||
.shutdown = sctp_shutdown,
|
||||
.setsockopt = sctp_setsockopt,
|
||||
.getsockopt = sctp_getsockopt,
|
||||
.bpf_bypass_getsockopt = sctp_bpf_bypass_getsockopt,
|
||||
.sendmsg = sctp_sendmsg,
|
||||
.recvmsg = sctp_recvmsg,
|
||||
.bind = sctp_bind,
|
||||
|
||||
@@ -791,6 +791,12 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
|
||||
struct svc_rdma_recv_ctxt *ctxt;
|
||||
int ret;
|
||||
|
||||
/* Prevent svc_xprt_release() from releasing pages in rq_pages
|
||||
* when returning 0 or an error.
|
||||
*/
|
||||
rqstp->rq_respages = rqstp->rq_pages;
|
||||
rqstp->rq_next_page = rqstp->rq_respages;
|
||||
|
||||
rqstp->rq_xprt_ctxt = NULL;
|
||||
|
||||
ctxt = NULL;
|
||||
@@ -814,12 +820,6 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
|
||||
DMA_FROM_DEVICE);
|
||||
svc_rdma_build_arg_xdr(rqstp, ctxt);
|
||||
|
||||
/* Prevent svc_xprt_release from releasing pages in rq_pages
|
||||
* if we return 0 or an error.
|
||||
*/
|
||||
rqstp->rq_respages = rqstp->rq_pages;
|
||||
rqstp->rq_next_page = rqstp->rq_respages;
|
||||
|
||||
ret = svc_rdma_xdr_decode_req(&rqstp->rq_arg, ctxt);
|
||||
if (ret < 0)
|
||||
goto out_err;
|
||||
|
||||
@@ -47,7 +47,7 @@ int bpf_basertt(struct bpf_sock_ops *skops)
|
||||
case BPF_SOCK_OPS_BASE_RTT:
|
||||
n = bpf_getsockopt(skops, SOL_TCP, TCP_CONGESTION,
|
||||
cong, sizeof(cong));
|
||||
if (!n && !__builtin_memcmp(cong, nv, sizeof(nv)+1)) {
|
||||
if (!n && !__builtin_memcmp(cong, nv, sizeof(nv))) {
|
||||
/* Set base_rtt to 80us */
|
||||
rv = 80;
|
||||
} else if (n) {
|
||||
|
||||
@@ -40,7 +40,7 @@ static const char evm_hmac[] = "hmac(sha1)";
|
||||
/**
|
||||
* evm_set_key() - set EVM HMAC key from the kernel
|
||||
* @key: pointer to a buffer with the key data
|
||||
* @size: length of the key data
|
||||
* @keylen: length of the key data
|
||||
*
|
||||
* This function allows setting the EVM HMAC key from the kernel
|
||||
* without using the "encrypted" key subsystem keys. It can be used
|
||||
|
||||
@@ -324,7 +324,6 @@ int evm_protected_xattr_if_enabled(const char *req_xattr_name)
|
||||
/**
|
||||
* evm_read_protected_xattrs - read EVM protected xattr names, lengths, values
|
||||
* @dentry: dentry of the read xattrs
|
||||
* @inode: inode of the read xattrs
|
||||
* @buffer: buffer xattr names, lengths or values are copied to
|
||||
* @buffer_size: size of buffer
|
||||
* @type: n: names, l: lengths, v: values
|
||||
@@ -396,6 +395,7 @@ int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
|
||||
* @xattr_name: requested xattr
|
||||
* @xattr_value: requested xattr value
|
||||
* @xattr_value_len: requested xattr value length
|
||||
* @iint: inode integrity metadata
|
||||
*
|
||||
* Calculate the HMAC for the given dentry and verify it against the stored
|
||||
* security.evm xattr. For performance, use the xattr value and length
|
||||
@@ -770,7 +770,9 @@ static int evm_attr_change(struct dentry *dentry, struct iattr *attr)
|
||||
|
||||
/**
|
||||
* evm_inode_setattr - prevent updating an invalid EVM extended attribute
|
||||
* @idmap: idmap of the mount
|
||||
* @dentry: pointer to the affected dentry
|
||||
* @attr: iattr structure containing the new file attributes
|
||||
*
|
||||
* Permit update of file attributes when files have a valid EVM signature,
|
||||
* except in the case of them having an immutable portable signature.
|
||||
|
||||
@@ -89,6 +89,9 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
|
||||
|
||||
/**
|
||||
* ima_collect_modsig - Calculate the file hash without the appended signature.
|
||||
* @modsig: parsed module signature
|
||||
* @buf: data to verify the signature on
|
||||
* @size: data size
|
||||
*
|
||||
* Since the modsig is part of the file contents, the hash used in its signature
|
||||
* isn't the same one ordinarily calculated by IMA. Therefore PKCS7 code
|
||||
|
||||
@@ -674,6 +674,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
|
||||
* @secid: LSM secid of the task to be validated
|
||||
* @func: IMA hook identifier
|
||||
* @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
|
||||
* @flags: IMA actions to consider (e.g. IMA_MEASURE | IMA_APPRAISE)
|
||||
* @pcr: set the pcr to extend
|
||||
* @template_desc: the template that should be used for this rule
|
||||
* @func_data: func specific data, may be NULL
|
||||
@@ -1709,7 +1710,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
|
||||
/**
|
||||
* ima_parse_add_rule - add a rule to ima_policy_rules
|
||||
* @rule - ima measurement policy rule
|
||||
* @rule: ima measurement policy rule
|
||||
*
|
||||
* Avoid locking by allowing just one writer at a time in ima_write_policy()
|
||||
* Returns the length of the rule parsed, an error code on failure
|
||||
|
||||
@@ -135,12 +135,12 @@ static void print_end_section(void)
|
||||
|
||||
/* Probing functions */
|
||||
|
||||
static int read_procfs(const char *path)
|
||||
static long read_procfs(const char *path)
|
||||
{
|
||||
char *endptr, *line = NULL;
|
||||
size_t len = 0;
|
||||
FILE *fd;
|
||||
int res;
|
||||
long res;
|
||||
|
||||
fd = fopen(path, "r");
|
||||
if (!fd)
|
||||
@@ -162,7 +162,7 @@ static int read_procfs(const char *path)
|
||||
|
||||
static void probe_unprivileged_disabled(void)
|
||||
{
|
||||
int res;
|
||||
long res;
|
||||
|
||||
/* No support for C-style ouptut */
|
||||
|
||||
@@ -181,14 +181,14 @@ static void probe_unprivileged_disabled(void)
|
||||
printf("Unable to retrieve required privileges for bpf() syscall\n");
|
||||
break;
|
||||
default:
|
||||
printf("bpf() syscall restriction has unknown value %d\n", res);
|
||||
printf("bpf() syscall restriction has unknown value %ld\n", res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void probe_jit_enable(void)
|
||||
{
|
||||
int res;
|
||||
long res;
|
||||
|
||||
/* No support for C-style ouptut */
|
||||
|
||||
@@ -210,7 +210,7 @@ static void probe_jit_enable(void)
|
||||
printf("Unable to retrieve JIT-compiler status\n");
|
||||
break;
|
||||
default:
|
||||
printf("JIT-compiler status has unknown value %d\n",
|
||||
printf("JIT-compiler status has unknown value %ld\n",
|
||||
res);
|
||||
}
|
||||
}
|
||||
@@ -218,7 +218,7 @@ static void probe_jit_enable(void)
|
||||
|
||||
static void probe_jit_harden(void)
|
||||
{
|
||||
int res;
|
||||
long res;
|
||||
|
||||
/* No support for C-style ouptut */
|
||||
|
||||
@@ -240,7 +240,7 @@ static void probe_jit_harden(void)
|
||||
printf("Unable to retrieve JIT hardening status\n");
|
||||
break;
|
||||
default:
|
||||
printf("JIT hardening status has unknown value %d\n",
|
||||
printf("JIT hardening status has unknown value %ld\n",
|
||||
res);
|
||||
}
|
||||
}
|
||||
@@ -248,7 +248,7 @@ static void probe_jit_harden(void)
|
||||
|
||||
static void probe_jit_kallsyms(void)
|
||||
{
|
||||
int res;
|
||||
long res;
|
||||
|
||||
/* No support for C-style ouptut */
|
||||
|
||||
@@ -267,14 +267,14 @@ static void probe_jit_kallsyms(void)
|
||||
printf("Unable to retrieve JIT kallsyms export status\n");
|
||||
break;
|
||||
default:
|
||||
printf("JIT kallsyms exports status has unknown value %d\n", res);
|
||||
printf("JIT kallsyms exports status has unknown value %ld\n", res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void probe_jit_limit(void)
|
||||
{
|
||||
int res;
|
||||
long res;
|
||||
|
||||
/* No support for C-style ouptut */
|
||||
|
||||
@@ -287,7 +287,7 @@ static void probe_jit_limit(void)
|
||||
printf("Unable to retrieve global memory limit for JIT compiler for unprivileged users\n");
|
||||
break;
|
||||
default:
|
||||
printf("Global memory limit for JIT compiler for unprivileged users is %d bytes\n", res);
|
||||
printf("Global memory limit for JIT compiler for unprivileged users is %ld bytes\n", res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,16 +72,21 @@
|
||||
/*
|
||||
* Helper macros to manipulate data structures
|
||||
*/
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((unsigned long)&((TYPE *)0)->MEMBER)
|
||||
#endif
|
||||
#ifndef container_of
|
||||
|
||||
/* offsetof() definition that uses __builtin_offset() might not preserve field
|
||||
* offset CO-RE relocation properly, so force-redefine offsetof() using
|
||||
* old-school approach which works with CO-RE correctly
|
||||
*/
|
||||
#undef offsetof
|
||||
#define offsetof(type, member) ((unsigned long)&((type *)0)->member)
|
||||
|
||||
/* redefined container_of() to ensure we use the above offsetof() macro */
|
||||
#undef container_of
|
||||
#define container_of(ptr, type, member) \
|
||||
({ \
|
||||
void *__mptr = (void *)(ptr); \
|
||||
((type *)(__mptr - offsetof(type, member))); \
|
||||
})
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper macro to throw a compilation error if __bpf_unreachable() gets
|
||||
|
||||
@@ -2126,9 +2126,25 @@ static int btf_dump_type_data_check_overflow(struct btf_dump *d,
|
||||
const struct btf_type *t,
|
||||
__u32 id,
|
||||
const void *data,
|
||||
__u8 bits_offset)
|
||||
__u8 bits_offset,
|
||||
__u8 bit_sz)
|
||||
{
|
||||
__s64 size = btf__resolve_size(d->btf, id);
|
||||
__s64 size;
|
||||
|
||||
if (bit_sz) {
|
||||
/* bits_offset is at most 7. bit_sz is at most 128. */
|
||||
__u8 nr_bytes = (bits_offset + bit_sz + 7) / 8;
|
||||
|
||||
/* When bit_sz is non zero, it is called from
|
||||
* btf_dump_struct_data() where it only cares about
|
||||
* negative error value.
|
||||
* Return nr_bytes in success case to make it
|
||||
* consistent as the regular integer case below.
|
||||
*/
|
||||
return data + nr_bytes > d->typed_dump->data_end ? -E2BIG : nr_bytes;
|
||||
}
|
||||
|
||||
size = btf__resolve_size(d->btf, id);
|
||||
|
||||
if (size < 0 || size >= INT_MAX) {
|
||||
pr_warn("unexpected size [%zu] for id [%u]\n",
|
||||
@@ -2281,7 +2297,7 @@ static int btf_dump_dump_type_data(struct btf_dump *d,
|
||||
{
|
||||
int size, err = 0;
|
||||
|
||||
size = btf_dump_type_data_check_overflow(d, t, id, data, bits_offset);
|
||||
size = btf_dump_type_data_check_overflow(d, t, id, data, bits_offset, bit_sz);
|
||||
if (size < 0)
|
||||
return size;
|
||||
err = btf_dump_type_data_check_zero(d, t, id, data, bits_offset, bit_sz);
|
||||
|
||||
@@ -197,7 +197,7 @@ cleanup:
|
||||
|
||||
void test_check_mtu(void)
|
||||
{
|
||||
__u32 mtu_lo;
|
||||
int mtu_lo;
|
||||
|
||||
if (test__start_subtest("bpf_check_mtu XDP-attach"))
|
||||
test_check_mtu_xdp_attach();
|
||||
|
||||
@@ -5,4 +5,4 @@ rcutree.gp_init_delay=3
|
||||
rcutree.gp_cleanup_delay=3
|
||||
rcutree.kthread_prio=2
|
||||
threadirqs
|
||||
tree.use_softirq=0
|
||||
rcutree.use_softirq=0
|
||||
|
||||
@@ -4,4 +4,4 @@ rcutree.gp_init_delay=3
|
||||
rcutree.gp_cleanup_delay=3
|
||||
rcutree.kthread_prio=2
|
||||
threadirqs
|
||||
tree.use_softirq=0
|
||||
rcutree.use_softirq=0
|
||||
|
||||
@@ -84,12 +84,12 @@ static inline int vdso_test_clock(unsigned int clock_id)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
#if _POSIX_TIMERS > 0
|
||||
|
||||
#ifdef CLOCK_REALTIME
|
||||
ret = vdso_test_clock(CLOCK_REALTIME);
|
||||
ret += vdso_test_clock(CLOCK_REALTIME);
|
||||
#endif
|
||||
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
|
||||
Reference in New Issue
Block a user