mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
Merge a298df1bbe ("usb: dwc3: Fix timeout issue during controller enter/exit from halt state") into android14-6.1-lts
Steps on the way to 6.1.129 Resolves merge conflicts in: drivers/pps/clients/pps-ldisc.c Change-Id: Idc1822210eb87723c7e7e34ad8ba71d2ca1d4ad3 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -87,16 +87,18 @@ int populate_cache_leaves(unsigned int cpu)
|
||||
unsigned int level, idx;
|
||||
enum cache_type type;
|
||||
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
|
||||
struct cacheinfo *this_leaf = this_cpu_ci->info_list;
|
||||
struct cacheinfo *infos = this_cpu_ci->info_list;
|
||||
|
||||
for (idx = 0, level = 1; level <= this_cpu_ci->num_levels &&
|
||||
idx < this_cpu_ci->num_leaves; idx++, level++) {
|
||||
idx < this_cpu_ci->num_leaves; level++) {
|
||||
type = get_cache_type(level);
|
||||
if (type == CACHE_TYPE_SEPARATE) {
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
|
||||
if (idx + 1 >= this_cpu_ci->num_leaves)
|
||||
break;
|
||||
ci_leaf_init(&infos[idx++], CACHE_TYPE_DATA, level);
|
||||
ci_leaf_init(&infos[idx++], CACHE_TYPE_INST, level);
|
||||
} else {
|
||||
ci_leaf_init(this_leaf++, type, level);
|
||||
ci_leaf_init(&infos[idx++], type, level);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -4582,8 +4582,11 @@ static void intel_pmu_cpu_starting(int cpu)
|
||||
|
||||
init_debug_store_on_cpu(cpu);
|
||||
/*
|
||||
* Deal with CPUs that don't clear their LBRs on power-up.
|
||||
* Deal with CPUs that don't clear their LBRs on power-up, and that may
|
||||
* even boot with LBRs enabled.
|
||||
*/
|
||||
if (!static_cpu_has(X86_FEATURE_ARCH_LBR) && x86_pmu.lbr_nr)
|
||||
msr_clear_bit(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR_BIT);
|
||||
intel_pmu_lbr_reset();
|
||||
|
||||
cpuc->lbr_sel = NULL;
|
||||
|
||||
@@ -33,6 +33,8 @@ typedef struct {
|
||||
*/
|
||||
atomic64_t tlb_gen;
|
||||
|
||||
unsigned long next_trim_cpumask;
|
||||
|
||||
#ifdef CONFIG_MODIFY_LDT_SYSCALL
|
||||
struct rw_semaphore ldt_usr_sem;
|
||||
struct ldt_struct *ldt;
|
||||
|
||||
@@ -106,6 +106,7 @@ static inline int init_new_context(struct task_struct *tsk,
|
||||
|
||||
mm->context.ctx_id = atomic64_inc_return(&last_mm_ctx_id);
|
||||
atomic64_set(&mm->context.tlb_gen, 0);
|
||||
mm->context.next_trim_cpumask = jiffies + HZ;
|
||||
|
||||
#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
|
||||
if (cpu_feature_enabled(X86_FEATURE_OSPKE)) {
|
||||
|
||||
@@ -357,7 +357,8 @@
|
||||
#define MSR_IA32_PASID_VALID BIT_ULL(31)
|
||||
|
||||
/* DEBUGCTLMSR bits (others vary by model): */
|
||||
#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */
|
||||
#define DEBUGCTLMSR_LBR_BIT 0 /* last branch recording */
|
||||
#define DEBUGCTLMSR_LBR (1UL << DEBUGCTLMSR_LBR_BIT)
|
||||
#define DEBUGCTLMSR_BTF_SHIFT 1
|
||||
#define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */
|
||||
#define DEBUGCTLMSR_BUS_LOCK_DETECT (1UL << 2)
|
||||
|
||||
@@ -208,6 +208,7 @@ struct flush_tlb_info {
|
||||
unsigned int initiating_cpu;
|
||||
u8 stride_shift;
|
||||
u8 freed_tables;
|
||||
u8 trim_cpumask;
|
||||
};
|
||||
|
||||
void flush_tlb_local(void);
|
||||
|
||||
@@ -1915,6 +1915,9 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
u32 vector;
|
||||
bool all_cpus;
|
||||
|
||||
if (!lapic_in_kernel(vcpu))
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
|
||||
if (hc->code == HVCALL_SEND_IPI) {
|
||||
if (!hc->fast) {
|
||||
if (unlikely(kvm_read_guest(kvm, hc->ingpa, &send_ipi,
|
||||
@@ -2518,7 +2521,8 @@ int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
|
||||
ent->eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED;
|
||||
ent->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
|
||||
ent->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
|
||||
ent->eax |= HV_X64_CLUSTER_IPI_RECOMMENDED;
|
||||
if (!vcpu || lapic_in_kernel(vcpu))
|
||||
ent->eax |= HV_X64_CLUSTER_IPI_RECOMMENDED;
|
||||
ent->eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED;
|
||||
if (evmcs_ver)
|
||||
ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
|
||||
|
||||
@@ -5150,7 +5150,7 @@ void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0,
|
||||
union kvm_mmu_page_role root_role;
|
||||
|
||||
/* NPT requires CR0.PG=1. */
|
||||
WARN_ON_ONCE(cpu_role.base.direct);
|
||||
WARN_ON_ONCE(cpu_role.base.direct || !cpu_role.base.guest_mode);
|
||||
|
||||
root_role = cpu_role.base;
|
||||
root_role.level = kvm_mmu_get_tdp_level(vcpu);
|
||||
|
||||
@@ -619,6 +619,11 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm,
|
||||
u32 pause_count12;
|
||||
u32 pause_thresh12;
|
||||
|
||||
nested_svm_transition_tlb_flush(vcpu);
|
||||
|
||||
/* Enter Guest-Mode */
|
||||
enter_guest_mode(vcpu);
|
||||
|
||||
/*
|
||||
* Filled at exit: exit_code, exit_code_hi, exit_info_1, exit_info_2,
|
||||
* exit_int_info, exit_int_info_err, next_rip, insn_len, insn_bytes.
|
||||
@@ -717,11 +722,6 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm,
|
||||
}
|
||||
}
|
||||
|
||||
nested_svm_transition_tlb_flush(vcpu);
|
||||
|
||||
/* Enter Guest-Mode */
|
||||
enter_guest_mode(vcpu);
|
||||
|
||||
/*
|
||||
* Merge guest and host intercepts - must be called with vcpu in
|
||||
* guest-mode to take effect.
|
||||
|
||||
@@ -878,9 +878,36 @@ done:
|
||||
nr_invalidate);
|
||||
}
|
||||
|
||||
static bool tlb_is_not_lazy(int cpu, void *data)
|
||||
static bool should_flush_tlb(int cpu, void *data)
|
||||
{
|
||||
return !per_cpu(cpu_tlbstate_shared.is_lazy, cpu);
|
||||
struct flush_tlb_info *info = data;
|
||||
|
||||
/* Lazy TLB will get flushed at the next context switch. */
|
||||
if (per_cpu(cpu_tlbstate_shared.is_lazy, cpu))
|
||||
return false;
|
||||
|
||||
/* No mm means kernel memory flush. */
|
||||
if (!info->mm)
|
||||
return true;
|
||||
|
||||
/* The target mm is loaded, and the CPU is not lazy. */
|
||||
if (per_cpu(cpu_tlbstate.loaded_mm, cpu) == info->mm)
|
||||
return true;
|
||||
|
||||
/* In cpumask, but not the loaded mm? Periodically remove by flushing. */
|
||||
if (info->trim_cpumask)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool should_trim_cpumask(struct mm_struct *mm)
|
||||
{
|
||||
if (time_after(jiffies, READ_ONCE(mm->context.next_trim_cpumask))) {
|
||||
WRITE_ONCE(mm->context.next_trim_cpumask, jiffies + HZ);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state_shared, cpu_tlbstate_shared);
|
||||
@@ -914,7 +941,7 @@ STATIC_NOPV void native_flush_tlb_multi(const struct cpumask *cpumask,
|
||||
if (info->freed_tables)
|
||||
on_each_cpu_mask(cpumask, flush_tlb_func, (void *)info, true);
|
||||
else
|
||||
on_each_cpu_cond_mask(tlb_is_not_lazy, flush_tlb_func,
|
||||
on_each_cpu_cond_mask(should_flush_tlb, flush_tlb_func,
|
||||
(void *)info, 1, cpumask);
|
||||
}
|
||||
|
||||
@@ -965,6 +992,7 @@ static struct flush_tlb_info *get_flush_tlb_info(struct mm_struct *mm,
|
||||
info->freed_tables = freed_tables;
|
||||
info->new_tlb_gen = new_tlb_gen;
|
||||
info->initiating_cpu = smp_processor_id();
|
||||
info->trim_cpumask = 0;
|
||||
|
||||
return info;
|
||||
}
|
||||
@@ -1007,6 +1035,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
|
||||
* flush_tlb_func_local() directly in this case.
|
||||
*/
|
||||
if (cpumask_any_but(mm_cpumask(mm), cpu) < nr_cpu_ids) {
|
||||
info->trim_cpumask = should_trim_cpumask(mm);
|
||||
flush_tlb_multi(mm_cpumask(mm), info);
|
||||
} else if (mm == this_cpu_read(cpu_tlbstate.loaded_mm)) {
|
||||
lockdep_assert_irqs_enabled();
|
||||
|
||||
@@ -97,6 +97,51 @@ static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss;
|
||||
*/
|
||||
static DEFINE_SPINLOCK(xen_reservation_lock);
|
||||
|
||||
/* Protected by xen_reservation_lock. */
|
||||
#define MIN_CONTIG_ORDER 9 /* 2MB */
|
||||
static unsigned int discontig_frames_order = MIN_CONTIG_ORDER;
|
||||
static unsigned long discontig_frames_early[1UL << MIN_CONTIG_ORDER] __initdata;
|
||||
static unsigned long *discontig_frames __refdata = discontig_frames_early;
|
||||
static bool discontig_frames_dyn;
|
||||
|
||||
static int alloc_discontig_frames(unsigned int order)
|
||||
{
|
||||
unsigned long *new_array, *old_array;
|
||||
unsigned int old_order;
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(order < MIN_CONTIG_ORDER);
|
||||
BUILD_BUG_ON(sizeof(discontig_frames_early) != PAGE_SIZE);
|
||||
|
||||
new_array = (unsigned long *)__get_free_pages(GFP_KERNEL,
|
||||
order - MIN_CONTIG_ORDER);
|
||||
if (!new_array)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&xen_reservation_lock, flags);
|
||||
|
||||
old_order = discontig_frames_order;
|
||||
|
||||
if (order > discontig_frames_order || !discontig_frames_dyn) {
|
||||
if (!discontig_frames_dyn)
|
||||
old_array = NULL;
|
||||
else
|
||||
old_array = discontig_frames;
|
||||
|
||||
discontig_frames = new_array;
|
||||
discontig_frames_order = order;
|
||||
discontig_frames_dyn = true;
|
||||
} else {
|
||||
old_array = new_array;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&xen_reservation_lock, flags);
|
||||
|
||||
free_pages((unsigned long)old_array, old_order - MIN_CONTIG_ORDER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note about cr3 (pagetable base) values:
|
||||
*
|
||||
@@ -766,6 +811,7 @@ void xen_mm_pin_all(void)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
spin_lock(&pgd_lock);
|
||||
|
||||
list_for_each_entry(page, &pgd_list, lru) {
|
||||
@@ -776,6 +822,7 @@ void xen_mm_pin_all(void)
|
||||
}
|
||||
|
||||
spin_unlock(&pgd_lock);
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
}
|
||||
|
||||
static void __init xen_mark_pinned(struct mm_struct *mm, struct page *page,
|
||||
@@ -797,6 +844,9 @@ static void __init xen_after_bootmem(void)
|
||||
SetPagePinned(virt_to_page(level3_user_vsyscall));
|
||||
#endif
|
||||
xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP);
|
||||
|
||||
if (alloc_discontig_frames(MIN_CONTIG_ORDER))
|
||||
BUG();
|
||||
}
|
||||
|
||||
static void xen_unpin_page(struct mm_struct *mm, struct page *page,
|
||||
@@ -872,6 +922,7 @@ void xen_mm_unpin_all(void)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
spin_lock(&pgd_lock);
|
||||
|
||||
list_for_each_entry(page, &pgd_list, lru) {
|
||||
@@ -883,6 +934,7 @@ void xen_mm_unpin_all(void)
|
||||
}
|
||||
|
||||
spin_unlock(&pgd_lock);
|
||||
spin_unlock(&init_mm.page_table_lock);
|
||||
}
|
||||
|
||||
static void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
|
||||
@@ -2177,10 +2229,6 @@ void __init xen_init_mmu_ops(void)
|
||||
memset(dummy_mapping, 0xff, PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* Protected by xen_reservation_lock. */
|
||||
#define MAX_CONTIG_ORDER 9 /* 2MB */
|
||||
static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
|
||||
|
||||
#define VOID_PTE (mfn_pte(0, __pgprot(0)))
|
||||
static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order,
|
||||
unsigned long *in_frames,
|
||||
@@ -2297,24 +2345,25 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
|
||||
unsigned int address_bits,
|
||||
dma_addr_t *dma_handle)
|
||||
{
|
||||
unsigned long *in_frames = discontig_frames, out_frame;
|
||||
unsigned long *in_frames, out_frame;
|
||||
unsigned long flags;
|
||||
int success;
|
||||
unsigned long vstart = (unsigned long)phys_to_virt(pstart);
|
||||
|
||||
/*
|
||||
* Currently an auto-translated guest will not perform I/O, nor will
|
||||
* it require PAE page directories below 4GB. Therefore any calls to
|
||||
* this function are redundant and can be ignored.
|
||||
*/
|
||||
if (unlikely(order > discontig_frames_order)) {
|
||||
if (!discontig_frames_dyn)
|
||||
return -ENOMEM;
|
||||
|
||||
if (unlikely(order > MAX_CONTIG_ORDER))
|
||||
return -ENOMEM;
|
||||
if (alloc_discontig_frames(order))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset((void *) vstart, 0, PAGE_SIZE << order);
|
||||
|
||||
spin_lock_irqsave(&xen_reservation_lock, flags);
|
||||
|
||||
in_frames = discontig_frames;
|
||||
|
||||
/* 1. Zap current PTEs, remembering MFNs. */
|
||||
xen_zap_pfn_range(vstart, order, in_frames, NULL);
|
||||
|
||||
@@ -2338,12 +2387,12 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
|
||||
|
||||
void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
|
||||
{
|
||||
unsigned long *out_frames = discontig_frames, in_frame;
|
||||
unsigned long *out_frames, in_frame;
|
||||
unsigned long flags;
|
||||
int success;
|
||||
unsigned long vstart;
|
||||
|
||||
if (unlikely(order > MAX_CONTIG_ORDER))
|
||||
if (unlikely(order > discontig_frames_order))
|
||||
return;
|
||||
|
||||
vstart = (unsigned long)phys_to_virt(pstart);
|
||||
@@ -2351,6 +2400,8 @@ void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
|
||||
|
||||
spin_lock_irqsave(&xen_reservation_lock, flags);
|
||||
|
||||
out_frames = discontig_frames;
|
||||
|
||||
/* 1. Find start MFN of contiguous extent. */
|
||||
in_frame = virt_to_mfn(vstart);
|
||||
|
||||
|
||||
@@ -68,6 +68,22 @@ struct bcm_kona_gpio {
|
||||
struct bcm_kona_gpio_bank {
|
||||
int id;
|
||||
int irq;
|
||||
/*
|
||||
* Used to keep track of lock/unlock operations for each GPIO in the
|
||||
* bank.
|
||||
*
|
||||
* All GPIOs are locked by default (see bcm_kona_gpio_reset), and the
|
||||
* unlock count for all GPIOs is 0 by default. Each unlock increments
|
||||
* the counter, and each lock decrements the counter.
|
||||
*
|
||||
* The lock function only locks the GPIO once its unlock counter is
|
||||
* down to 0. This is necessary because the GPIO is unlocked in two
|
||||
* places in this driver: once for requested GPIOs, and once for
|
||||
* requested IRQs. Since it is possible for a GPIO to be requested
|
||||
* as both a GPIO and an IRQ, we need to ensure that we don't lock it
|
||||
* too early.
|
||||
*/
|
||||
u8 gpio_unlock_count[GPIO_PER_BANK];
|
||||
/* Used in the interrupt handler */
|
||||
struct bcm_kona_gpio *kona_gpio;
|
||||
};
|
||||
@@ -85,14 +101,24 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio,
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
int bit = GPIO_BIT(gpio);
|
||||
struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id];
|
||||
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
if (bank->gpio_unlock_count[bit] == 0) {
|
||||
dev_err(kona_gpio->gpio_chip.parent,
|
||||
"Unbalanced locks for GPIO %u\n", gpio);
|
||||
return;
|
||||
}
|
||||
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val |= BIT(gpio);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
if (--bank->gpio_unlock_count[bit] == 0) {
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val |= BIT(bit);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
|
||||
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
|
||||
@@ -101,14 +127,20 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
int bank_id = GPIO_BANK(gpio);
|
||||
int bit = GPIO_BIT(gpio);
|
||||
struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id];
|
||||
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
if (bank->gpio_unlock_count[bit] == 0) {
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val &= ~BIT(gpio);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
|
||||
val &= ~BIT(bit);
|
||||
bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
|
||||
|
||||
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
|
||||
}
|
||||
|
||||
++bank->gpio_unlock_count[bit];
|
||||
}
|
||||
|
||||
static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
|
||||
@@ -359,6 +391,7 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d)
|
||||
|
||||
kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
val = readl(reg_base + GPIO_INT_MASK(bank_id));
|
||||
@@ -381,6 +414,7 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
|
||||
|
||||
kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
reg_base = kona_gpio->reg_base;
|
||||
|
||||
raw_spin_lock_irqsave(&kona_gpio->lock, flags);
|
||||
|
||||
val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
|
||||
@@ -476,15 +510,26 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc)
|
||||
static int bcm_kona_gpio_irq_reqres(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
unsigned int gpio = d->hwirq;
|
||||
|
||||
return gpiochip_reqres_irq(&kona_gpio->gpio_chip, d->hwirq);
|
||||
/*
|
||||
* We need to unlock the GPIO before any other operations are performed
|
||||
* on the relevant GPIO configuration registers
|
||||
*/
|
||||
bcm_kona_gpio_unlock_gpio(kona_gpio, gpio);
|
||||
|
||||
return gpiochip_reqres_irq(&kona_gpio->gpio_chip, gpio);
|
||||
}
|
||||
|
||||
static void bcm_kona_gpio_irq_relres(struct irq_data *d)
|
||||
{
|
||||
struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
|
||||
unsigned int gpio = d->hwirq;
|
||||
|
||||
gpiochip_relres_irq(&kona_gpio->gpio_chip, d->hwirq);
|
||||
/* Once we no longer use it, lock the GPIO again */
|
||||
bcm_kona_gpio_lock_gpio(kona_gpio, gpio);
|
||||
|
||||
gpiochip_relres_irq(&kona_gpio->gpio_chip, gpio);
|
||||
}
|
||||
|
||||
static struct irq_chip bcm_gpio_irq_chip = {
|
||||
@@ -622,7 +667,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
|
||||
bank->irq = platform_get_irq(pdev, i);
|
||||
bank->kona_gpio = kona_gpio;
|
||||
if (bank->irq < 0) {
|
||||
dev_err(dev, "Couldn't get IRQ for bank %d", i);
|
||||
dev_err(dev, "Couldn't get IRQ for bank %d\n", i);
|
||||
ret = -ENOENT;
|
||||
goto err_irq_domain;
|
||||
}
|
||||
|
||||
@@ -516,7 +516,8 @@ static int smu_sys_set_pp_table(void *handle,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!smu_table->hardcode_pptable) {
|
||||
if (!smu_table->hardcode_pptable || smu_table->power_play_table_size < size) {
|
||||
kfree(smu_table->hardcode_pptable);
|
||||
smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL);
|
||||
if (!smu_table->hardcode_pptable)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -164,7 +164,7 @@ static int igt_ppgtt_alloc(void *arg)
|
||||
return PTR_ERR(ppgtt);
|
||||
|
||||
if (!ppgtt->vm.allocate_va_range)
|
||||
goto err_ppgtt_cleanup;
|
||||
goto ppgtt_vm_put;
|
||||
|
||||
/*
|
||||
* While we only allocate the page tables here and so we could
|
||||
@@ -232,7 +232,7 @@ err_ppgtt_cleanup:
|
||||
goto retry;
|
||||
}
|
||||
i915_gem_ww_ctx_fini(&ww);
|
||||
|
||||
ppgtt_vm_put:
|
||||
i915_vm_put(&ppgtt->vm);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1668,9 +1668,12 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
||||
break;
|
||||
}
|
||||
|
||||
if (suffix)
|
||||
if (suffix) {
|
||||
hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
|
||||
"%s %s", hdev->name, suffix);
|
||||
if (!hi->input->name)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ static void thrustmaster_interrupts(struct hid_device *hdev)
|
||||
b_ep = ep->desc.bEndpointAddress;
|
||||
|
||||
/* Are the expected endpoints present? */
|
||||
u8 ep_addr[1] = {b_ep};
|
||||
u8 ep_addr[2] = {b_ep, 0};
|
||||
|
||||
if (!usb_check_int_endpoints(usbif, ep_addr)) {
|
||||
hid_err(hdev, "Unexpected non-int endpoint\n");
|
||||
|
||||
@@ -452,7 +452,6 @@ static void efa_ib_device_remove(struct efa_dev *dev)
|
||||
ibdev_info(&dev->ibdev, "Unregister ib device\n");
|
||||
ib_unregister_device(&dev->ibdev);
|
||||
efa_destroy_eqs(dev);
|
||||
efa_com_dev_reset(&dev->edev, EFA_REGS_RESET_NORMAL);
|
||||
efa_release_doorbell_bar(dev);
|
||||
}
|
||||
|
||||
@@ -623,12 +622,14 @@ err_disable_device:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static void efa_remove_device(struct pci_dev *pdev)
|
||||
static void efa_remove_device(struct pci_dev *pdev,
|
||||
enum efa_regs_reset_reason_types reset_reason)
|
||||
{
|
||||
struct efa_dev *dev = pci_get_drvdata(pdev);
|
||||
struct efa_com_dev *edev;
|
||||
|
||||
edev = &dev->edev;
|
||||
efa_com_dev_reset(edev, reset_reason);
|
||||
efa_com_admin_destroy(edev);
|
||||
efa_free_irq(dev, &dev->admin_irq);
|
||||
efa_disable_msix(dev);
|
||||
@@ -656,7 +657,7 @@ static int efa_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
return 0;
|
||||
|
||||
err_remove_device:
|
||||
efa_remove_device(pdev);
|
||||
efa_remove_device(pdev, EFA_REGS_RESET_INIT_ERR);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -665,7 +666,7 @@ static void efa_remove(struct pci_dev *pdev)
|
||||
struct efa_dev *dev = pci_get_drvdata(pdev);
|
||||
|
||||
efa_ib_device_remove(dev);
|
||||
efa_remove_device(pdev);
|
||||
efa_remove_device(pdev, EFA_REGS_RESET_NORMAL);
|
||||
}
|
||||
|
||||
static struct pci_driver efa_pci_driver = {
|
||||
|
||||
@@ -311,12 +311,8 @@ static int cxd2841er_set_reg_bits(struct cxd2841er_priv *priv,
|
||||
|
||||
static u32 cxd2841er_calc_iffreq_xtal(enum cxd2841er_xtal xtal, u32 ifhz)
|
||||
{
|
||||
u64 tmp;
|
||||
|
||||
tmp = (u64) ifhz * 16777216;
|
||||
do_div(tmp, ((xtal == SONY_XTAL_24000) ? 48000000 : 41000000));
|
||||
|
||||
return (u32) tmp;
|
||||
return div_u64(ifhz * 16777216ull,
|
||||
(xtal == SONY_XTAL_24000) ? 48000000 : 41000000);
|
||||
}
|
||||
|
||||
static u32 cxd2841er_calc_iffreq(u32 ifhz)
|
||||
|
||||
@@ -191,10 +191,11 @@ static int vidtv_start_streaming(struct vidtv_dvb *dvb)
|
||||
|
||||
mux_args.mux_buf_sz = mux_buf_sz;
|
||||
|
||||
dvb->streaming = true;
|
||||
dvb->mux = vidtv_mux_init(dvb->fe[0], dev, &mux_args);
|
||||
if (!dvb->mux)
|
||||
return -ENOMEM;
|
||||
|
||||
dvb->streaming = true;
|
||||
vidtv_mux_start_thread(dvb->mux);
|
||||
|
||||
dev_dbg_ratelimited(dev, "Started streaming\n");
|
||||
@@ -205,6 +206,11 @@ static int vidtv_stop_streaming(struct vidtv_dvb *dvb)
|
||||
{
|
||||
struct device *dev = &dvb->pdev->dev;
|
||||
|
||||
if (!dvb->streaming) {
|
||||
dev_warn_ratelimited(dev, "No streaming. Skipping.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvb->streaming = false;
|
||||
vidtv_mux_stop_thread(dvb->mux);
|
||||
vidtv_mux_destroy(dvb->mux);
|
||||
|
||||
@@ -2670,7 +2670,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
|
||||
ctx.data.u32_val = nla_get_u32(attr_data);
|
||||
break;
|
||||
case TEAM_OPTION_TYPE_STRING:
|
||||
if (nla_len(attr_data) > TEAM_STRING_MAX_LEN) {
|
||||
if (nla_len(attr_data) > TEAM_STRING_MAX_LEN ||
|
||||
!memchr(nla_data(attr_data), '\0',
|
||||
nla_len(attr_data))) {
|
||||
err = -EINVAL;
|
||||
goto team_put;
|
||||
}
|
||||
|
||||
@@ -2982,8 +2982,11 @@ static int vxlan_init(struct net_device *dev)
|
||||
struct vxlan_dev *vxlan = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
|
||||
vxlan_vnigroup_init(vxlan);
|
||||
if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) {
|
||||
err = vxlan_vnigroup_init(vxlan);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
||||
if (!dev->tstats) {
|
||||
|
||||
@@ -5870,6 +5870,17 @@ SWITCHTEC_QUIRK(0x5552); /* PAXA 52XG5 */
|
||||
SWITCHTEC_QUIRK(0x5536); /* PAXA 36XG5 */
|
||||
SWITCHTEC_QUIRK(0x5528); /* PAXA 28XG5 */
|
||||
|
||||
#define SWITCHTEC_PCI100X_QUIRK(vid) \
|
||||
DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_EFAR, vid, \
|
||||
PCI_CLASS_BRIDGE_OTHER, 8, quirk_switchtec_ntb_dma_alias)
|
||||
SWITCHTEC_PCI100X_QUIRK(0x1001); /* PCI1001XG4 */
|
||||
SWITCHTEC_PCI100X_QUIRK(0x1002); /* PCI1002XG4 */
|
||||
SWITCHTEC_PCI100X_QUIRK(0x1003); /* PCI1003XG4 */
|
||||
SWITCHTEC_PCI100X_QUIRK(0x1004); /* PCI1004XG4 */
|
||||
SWITCHTEC_PCI100X_QUIRK(0x1005); /* PCI1005XG4 */
|
||||
SWITCHTEC_PCI100X_QUIRK(0x1006); /* PCI1006XG4 */
|
||||
|
||||
|
||||
/*
|
||||
* The PLX NTB uses devfn proxy IDs to move TLPs between NT endpoints.
|
||||
* These IDs are used to forward responses to the originator on the other
|
||||
@@ -6139,6 +6150,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2b, dpc_log_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2d, dpc_log_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2f, dpc_log_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a31, dpc_log_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa72f, dpc_log_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa73f, dpc_log_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa76e, dpc_log_size);
|
||||
#endif
|
||||
|
||||
@@ -1739,6 +1739,26 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
|
||||
.driver_data = gen, \
|
||||
}
|
||||
|
||||
#define SWITCHTEC_PCI100X_DEVICE(device_id, gen) \
|
||||
{ \
|
||||
.vendor = PCI_VENDOR_ID_EFAR, \
|
||||
.device = device_id, \
|
||||
.subvendor = PCI_ANY_ID, \
|
||||
.subdevice = PCI_ANY_ID, \
|
||||
.class = (PCI_CLASS_MEMORY_OTHER << 8), \
|
||||
.class_mask = 0xFFFFFFFF, \
|
||||
.driver_data = gen, \
|
||||
}, \
|
||||
{ \
|
||||
.vendor = PCI_VENDOR_ID_EFAR, \
|
||||
.device = device_id, \
|
||||
.subvendor = PCI_ANY_ID, \
|
||||
.subdevice = PCI_ANY_ID, \
|
||||
.class = (PCI_CLASS_BRIDGE_OTHER << 8), \
|
||||
.class_mask = 0xFFFFFFFF, \
|
||||
.driver_data = gen, \
|
||||
}
|
||||
|
||||
static const struct pci_device_id switchtec_pci_tbl[] = {
|
||||
SWITCHTEC_PCI_DEVICE(0x8531, SWITCHTEC_GEN3), /* PFX 24xG3 */
|
||||
SWITCHTEC_PCI_DEVICE(0x8532, SWITCHTEC_GEN3), /* PFX 32xG3 */
|
||||
@@ -1833,6 +1853,12 @@ static const struct pci_device_id switchtec_pci_tbl[] = {
|
||||
SWITCHTEC_PCI_DEVICE(0x5552, SWITCHTEC_GEN5), /* PAXA 52XG5 */
|
||||
SWITCHTEC_PCI_DEVICE(0x5536, SWITCHTEC_GEN5), /* PAXA 36XG5 */
|
||||
SWITCHTEC_PCI_DEVICE(0x5528, SWITCHTEC_GEN5), /* PAXA 28XG5 */
|
||||
SWITCHTEC_PCI100X_DEVICE(0x1001, SWITCHTEC_GEN4), /* PCI1001 16XG4 */
|
||||
SWITCHTEC_PCI100X_DEVICE(0x1002, SWITCHTEC_GEN4), /* PCI1002 12XG4 */
|
||||
SWITCHTEC_PCI100X_DEVICE(0x1003, SWITCHTEC_GEN4), /* PCI1003 16XG4 */
|
||||
SWITCHTEC_PCI100X_DEVICE(0x1004, SWITCHTEC_GEN4), /* PCI1004 16XG4 */
|
||||
SWITCHTEC_PCI100X_DEVICE(0x1005, SWITCHTEC_GEN4), /* PCI1005 16XG4 */
|
||||
SWITCHTEC_PCI100X_DEVICE(0x1006, SWITCHTEC_GEN4), /* PCI1006 16XG4 */
|
||||
{0}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, switchtec_pci_tbl);
|
||||
|
||||
@@ -1234,7 +1234,7 @@ static int cy8c95x0_irq_setup(struct cy8c95x0_pinctrl *chip, int irq)
|
||||
|
||||
ret = devm_request_threaded_irq(chip->dev, irq,
|
||||
NULL, cy8c95x0_irq_handler,
|
||||
IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_HIGH,
|
||||
IRQF_ONESHOT | IRQF_SHARED,
|
||||
dev_name(chip->dev), chip);
|
||||
if (ret) {
|
||||
dev_err(chip->dev, "failed to request irq %d\n", irq);
|
||||
|
||||
@@ -214,8 +214,8 @@ static int pps_gpio_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n",
|
||||
data->irq);
|
||||
dev_dbg(&data->pps->dev, "Registered IRQ %d as PPS source\n",
|
||||
data->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ static struct pps_source_info pps_ktimer_info = {
|
||||
|
||||
static void __exit pps_ktimer_exit(void)
|
||||
{
|
||||
dev_info(pps->dev, "ktimer PPS source unregistered\n");
|
||||
dev_dbg(&pps->dev, "ktimer PPS source unregistered\n");
|
||||
|
||||
del_timer_sync(&ktimer);
|
||||
pps_unregister_source(pps);
|
||||
@@ -74,7 +74,7 @@ static int __init pps_ktimer_init(void)
|
||||
timer_setup(&ktimer, pps_ktimer_event, 0);
|
||||
mod_timer(&ktimer, jiffies + HZ);
|
||||
|
||||
dev_info(pps->dev, "ktimer PPS source registered\n");
|
||||
dev_dbg(&pps->dev, "ktimer PPS source registered\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status)
|
||||
pps_event(pps, &ts, status ? PPS_CAPTUREASSERT :
|
||||
PPS_CAPTURECLEAR, NULL);
|
||||
|
||||
dev_dbg(pps->dev, "PPS %s at %lu\n",
|
||||
dev_dbg(&pps->dev, "PPS %s at %lu\n",
|
||||
status ? "assert" : "clear", jiffies);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ static int pps_tty_open(struct tty_struct *tty)
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
dev_info(pps->dev, "source \"%s\" added\n", info.path);
|
||||
dev_dbg(&pps->dev, "source \"%s\" added\n", info.path);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -89,7 +89,7 @@ static void pps_tty_close(struct tty_struct *tty)
|
||||
if (WARN_ON(!pps))
|
||||
return;
|
||||
|
||||
dev_info(pps->dev, "removed\n");
|
||||
dev_info(&pps->dev, "removed\n");
|
||||
pps_unregister_source(pps);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ static void parport_irq(void *handle)
|
||||
/* check the signal (no signal means the pulse is lost this time) */
|
||||
if (!signal_is_set(port)) {
|
||||
local_irq_restore(flags);
|
||||
dev_err(dev->pps->dev, "lost the signal\n");
|
||||
dev_err(&dev->pps->dev, "lost the signal\n");
|
||||
goto out_assert;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ static void parport_irq(void *handle)
|
||||
/* timeout */
|
||||
dev->cw_err++;
|
||||
if (dev->cw_err >= CLEAR_WAIT_MAX_ERRORS) {
|
||||
dev_err(dev->pps->dev, "disabled clear edge capture after %d"
|
||||
dev_err(&dev->pps->dev, "disabled clear edge capture after %d"
|
||||
" timeouts\n", dev->cw_err);
|
||||
dev->cw = 0;
|
||||
dev->cw_err = 0;
|
||||
|
||||
@@ -41,7 +41,7 @@ static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
|
||||
static void pps_echo_client_default(struct pps_device *pps, int event,
|
||||
void *data)
|
||||
{
|
||||
dev_info(pps->dev, "echo %s %s\n",
|
||||
dev_info(&pps->dev, "echo %s %s\n",
|
||||
event & PPS_CAPTUREASSERT ? "assert" : "",
|
||||
event & PPS_CAPTURECLEAR ? "clear" : "");
|
||||
}
|
||||
@@ -112,7 +112,7 @@ struct pps_device *pps_register_source(struct pps_source_info *info,
|
||||
goto kfree_pps;
|
||||
}
|
||||
|
||||
dev_info(pps->dev, "new PPS source %s\n", info->name);
|
||||
dev_dbg(&pps->dev, "new PPS source %s\n", info->name);
|
||||
|
||||
return pps;
|
||||
|
||||
@@ -166,7 +166,7 @@ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
|
||||
/* check event type */
|
||||
BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0);
|
||||
|
||||
dev_dbg(pps->dev, "PPS event at %lld.%09ld\n",
|
||||
dev_dbg(&pps->dev, "PPS event at %lld.%09ld\n",
|
||||
(s64)ts->ts_real.tv_sec, ts->ts_real.tv_nsec);
|
||||
|
||||
timespec_to_pps_ktime(&ts_real, ts->ts_real);
|
||||
@@ -188,7 +188,7 @@ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
|
||||
/* Save the time stamp */
|
||||
pps->assert_tu = ts_real;
|
||||
pps->assert_sequence++;
|
||||
dev_dbg(pps->dev, "capture assert seq #%u\n",
|
||||
dev_dbg(&pps->dev, "capture assert seq #%u\n",
|
||||
pps->assert_sequence);
|
||||
|
||||
captured = ~0;
|
||||
@@ -202,7 +202,7 @@ void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
|
||||
/* Save the time stamp */
|
||||
pps->clear_tu = ts_real;
|
||||
pps->clear_sequence++;
|
||||
dev_dbg(pps->dev, "capture clear seq #%u\n",
|
||||
dev_dbg(&pps->dev, "capture clear seq #%u\n",
|
||||
pps->clear_sequence);
|
||||
|
||||
captured = ~0;
|
||||
|
||||
@@ -43,11 +43,11 @@ int pps_kc_bind(struct pps_device *pps, struct pps_bind_args *bind_args)
|
||||
pps_kc_hardpps_mode = 0;
|
||||
pps_kc_hardpps_dev = NULL;
|
||||
spin_unlock_irq(&pps_kc_hardpps_lock);
|
||||
dev_info(pps->dev, "unbound kernel"
|
||||
dev_info(&pps->dev, "unbound kernel"
|
||||
" consumer\n");
|
||||
} else {
|
||||
spin_unlock_irq(&pps_kc_hardpps_lock);
|
||||
dev_err(pps->dev, "selected kernel consumer"
|
||||
dev_err(&pps->dev, "selected kernel consumer"
|
||||
" is not bound\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -57,11 +57,11 @@ int pps_kc_bind(struct pps_device *pps, struct pps_bind_args *bind_args)
|
||||
pps_kc_hardpps_mode = bind_args->edge;
|
||||
pps_kc_hardpps_dev = pps;
|
||||
spin_unlock_irq(&pps_kc_hardpps_lock);
|
||||
dev_info(pps->dev, "bound kernel consumer: "
|
||||
dev_info(&pps->dev, "bound kernel consumer: "
|
||||
"edge=0x%x\n", bind_args->edge);
|
||||
} else {
|
||||
spin_unlock_irq(&pps_kc_hardpps_lock);
|
||||
dev_err(pps->dev, "another kernel consumer"
|
||||
dev_err(&pps->dev, "another kernel consumer"
|
||||
" is already bound\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ void pps_kc_remove(struct pps_device *pps)
|
||||
pps_kc_hardpps_mode = 0;
|
||||
pps_kc_hardpps_dev = NULL;
|
||||
spin_unlock_irq(&pps_kc_hardpps_lock);
|
||||
dev_info(pps->dev, "unbound kernel consumer"
|
||||
dev_info(&pps->dev, "unbound kernel consumer"
|
||||
" on device removal\n");
|
||||
} else
|
||||
spin_unlock_irq(&pps_kc_hardpps_lock);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* Local variables
|
||||
*/
|
||||
|
||||
static dev_t pps_devt;
|
||||
static int pps_major;
|
||||
static struct class *pps_class;
|
||||
|
||||
static DEFINE_MUTEX(pps_idr_lock);
|
||||
@@ -62,7 +62,7 @@ static int pps_cdev_pps_fetch(struct pps_device *pps, struct pps_fdata *fdata)
|
||||
else {
|
||||
unsigned long ticks;
|
||||
|
||||
dev_dbg(pps->dev, "timeout %lld.%09d\n",
|
||||
dev_dbg(&pps->dev, "timeout %lld.%09d\n",
|
||||
(long long) fdata->timeout.sec,
|
||||
fdata->timeout.nsec);
|
||||
ticks = fdata->timeout.sec * HZ;
|
||||
@@ -80,7 +80,7 @@ static int pps_cdev_pps_fetch(struct pps_device *pps, struct pps_fdata *fdata)
|
||||
|
||||
/* Check for pending signals */
|
||||
if (err == -ERESTARTSYS) {
|
||||
dev_dbg(pps->dev, "pending signal caught\n");
|
||||
dev_dbg(&pps->dev, "pending signal caught\n");
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
|
||||
switch (cmd) {
|
||||
case PPS_GETPARAMS:
|
||||
dev_dbg(pps->dev, "PPS_GETPARAMS\n");
|
||||
dev_dbg(&pps->dev, "PPS_GETPARAMS\n");
|
||||
|
||||
spin_lock_irq(&pps->lock);
|
||||
|
||||
@@ -114,7 +114,7 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
break;
|
||||
|
||||
case PPS_SETPARAMS:
|
||||
dev_dbg(pps->dev, "PPS_SETPARAMS\n");
|
||||
dev_dbg(&pps->dev, "PPS_SETPARAMS\n");
|
||||
|
||||
/* Check the capabilities */
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
@@ -124,14 +124,14 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
|
||||
dev_dbg(pps->dev, "capture mode unspecified (%x)\n",
|
||||
dev_dbg(&pps->dev, "capture mode unspecified (%x)\n",
|
||||
params.mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check for supported capabilities */
|
||||
if ((params.mode & ~pps->info.mode) != 0) {
|
||||
dev_dbg(pps->dev, "unsupported capabilities (%x)\n",
|
||||
dev_dbg(&pps->dev, "unsupported capabilities (%x)\n",
|
||||
params.mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -144,7 +144,7 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
/* Restore the read only parameters */
|
||||
if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
|
||||
/* section 3.3 of RFC 2783 interpreted */
|
||||
dev_dbg(pps->dev, "time format unspecified (%x)\n",
|
||||
dev_dbg(&pps->dev, "time format unspecified (%x)\n",
|
||||
params.mode);
|
||||
pps->params.mode |= PPS_TSFMT_TSPEC;
|
||||
}
|
||||
@@ -165,7 +165,7 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
break;
|
||||
|
||||
case PPS_GETCAP:
|
||||
dev_dbg(pps->dev, "PPS_GETCAP\n");
|
||||
dev_dbg(&pps->dev, "PPS_GETCAP\n");
|
||||
|
||||
err = put_user(pps->info.mode, iuarg);
|
||||
if (err)
|
||||
@@ -176,7 +176,7 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
case PPS_FETCH: {
|
||||
struct pps_fdata fdata;
|
||||
|
||||
dev_dbg(pps->dev, "PPS_FETCH\n");
|
||||
dev_dbg(&pps->dev, "PPS_FETCH\n");
|
||||
|
||||
err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata));
|
||||
if (err)
|
||||
@@ -206,7 +206,7 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
case PPS_KC_BIND: {
|
||||
struct pps_bind_args bind_args;
|
||||
|
||||
dev_dbg(pps->dev, "PPS_KC_BIND\n");
|
||||
dev_dbg(&pps->dev, "PPS_KC_BIND\n");
|
||||
|
||||
/* Check the capabilities */
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
@@ -218,7 +218,7 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
|
||||
/* Check for supported capabilities */
|
||||
if ((bind_args.edge & ~pps->info.mode) != 0) {
|
||||
dev_err(pps->dev, "unsupported capabilities (%x)\n",
|
||||
dev_err(&pps->dev, "unsupported capabilities (%x)\n",
|
||||
bind_args.edge);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -227,7 +227,7 @@ static long pps_cdev_ioctl(struct file *file,
|
||||
if (bind_args.tsformat != PPS_TSFMT_TSPEC ||
|
||||
(bind_args.edge & ~PPS_CAPTUREBOTH) != 0 ||
|
||||
bind_args.consumer != PPS_KC_HARDPPS) {
|
||||
dev_err(pps->dev, "invalid kernel consumer bind"
|
||||
dev_err(&pps->dev, "invalid kernel consumer bind"
|
||||
" parameters (%x)\n", bind_args.edge);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -259,7 +259,7 @@ static long pps_cdev_compat_ioctl(struct file *file,
|
||||
struct pps_fdata fdata;
|
||||
int err;
|
||||
|
||||
dev_dbg(pps->dev, "PPS_FETCH\n");
|
||||
dev_dbg(&pps->dev, "PPS_FETCH\n");
|
||||
|
||||
err = copy_from_user(&compat, uarg, sizeof(struct pps_fdata_compat));
|
||||
if (err)
|
||||
@@ -296,20 +296,36 @@ static long pps_cdev_compat_ioctl(struct file *file,
|
||||
#define pps_cdev_compat_ioctl NULL
|
||||
#endif
|
||||
|
||||
static struct pps_device *pps_idr_get(unsigned long id)
|
||||
{
|
||||
struct pps_device *pps;
|
||||
|
||||
mutex_lock(&pps_idr_lock);
|
||||
pps = idr_find(&pps_idr, id);
|
||||
if (pps)
|
||||
get_device(&pps->dev);
|
||||
|
||||
mutex_unlock(&pps_idr_lock);
|
||||
return pps;
|
||||
}
|
||||
|
||||
static int pps_cdev_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct pps_device *pps = container_of(inode->i_cdev,
|
||||
struct pps_device, cdev);
|
||||
struct pps_device *pps = pps_idr_get(iminor(inode));
|
||||
|
||||
if (!pps)
|
||||
return -ENODEV;
|
||||
|
||||
file->private_data = pps;
|
||||
kobject_get(&pps->dev->kobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pps_cdev_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct pps_device *pps = container_of(inode->i_cdev,
|
||||
struct pps_device, cdev);
|
||||
kobject_put(&pps->dev->kobj);
|
||||
struct pps_device *pps = file->private_data;
|
||||
|
||||
WARN_ON(pps->id != iminor(inode));
|
||||
put_device(&pps->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -332,22 +348,13 @@ static void pps_device_destruct(struct device *dev)
|
||||
{
|
||||
struct pps_device *pps = dev_get_drvdata(dev);
|
||||
|
||||
cdev_del(&pps->cdev);
|
||||
|
||||
/* Now we can release the ID for re-use */
|
||||
pr_debug("deallocating pps%d\n", pps->id);
|
||||
mutex_lock(&pps_idr_lock);
|
||||
idr_remove(&pps_idr, pps->id);
|
||||
mutex_unlock(&pps_idr_lock);
|
||||
|
||||
kfree(dev);
|
||||
kfree(pps);
|
||||
}
|
||||
|
||||
int pps_register_cdev(struct pps_device *pps)
|
||||
{
|
||||
int err;
|
||||
dev_t devt;
|
||||
|
||||
mutex_lock(&pps_idr_lock);
|
||||
/*
|
||||
@@ -364,40 +371,29 @@ int pps_register_cdev(struct pps_device *pps)
|
||||
goto out_unlock;
|
||||
}
|
||||
pps->id = err;
|
||||
mutex_unlock(&pps_idr_lock);
|
||||
|
||||
devt = MKDEV(MAJOR(pps_devt), pps->id);
|
||||
|
||||
cdev_init(&pps->cdev, &pps_cdev_fops);
|
||||
pps->cdev.owner = pps->info.owner;
|
||||
|
||||
err = cdev_add(&pps->cdev, devt, 1);
|
||||
if (err) {
|
||||
pr_err("%s: failed to add char device %d:%d\n",
|
||||
pps->info.name, MAJOR(pps_devt), pps->id);
|
||||
pps->dev.class = pps_class;
|
||||
pps->dev.parent = pps->info.dev;
|
||||
pps->dev.devt = MKDEV(pps_major, pps->id);
|
||||
dev_set_drvdata(&pps->dev, pps);
|
||||
dev_set_name(&pps->dev, "pps%d", pps->id);
|
||||
err = device_register(&pps->dev);
|
||||
if (err)
|
||||
goto free_idr;
|
||||
}
|
||||
pps->dev = device_create(pps_class, pps->info.dev, devt, pps,
|
||||
"pps%d", pps->id);
|
||||
if (IS_ERR(pps->dev)) {
|
||||
err = PTR_ERR(pps->dev);
|
||||
goto del_cdev;
|
||||
}
|
||||
|
||||
/* Override the release function with our own */
|
||||
pps->dev->release = pps_device_destruct;
|
||||
pps->dev.release = pps_device_destruct;
|
||||
|
||||
pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
|
||||
MAJOR(pps_devt), pps->id);
|
||||
pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, pps_major,
|
||||
pps->id);
|
||||
|
||||
get_device(&pps->dev);
|
||||
mutex_unlock(&pps_idr_lock);
|
||||
return 0;
|
||||
|
||||
del_cdev:
|
||||
cdev_del(&pps->cdev);
|
||||
|
||||
free_idr:
|
||||
mutex_lock(&pps_idr_lock);
|
||||
idr_remove(&pps_idr, pps->id);
|
||||
put_device(&pps->dev);
|
||||
out_unlock:
|
||||
mutex_unlock(&pps_idr_lock);
|
||||
return err;
|
||||
@@ -407,7 +403,13 @@ void pps_unregister_cdev(struct pps_device *pps)
|
||||
{
|
||||
pr_debug("unregistering pps%d\n", pps->id);
|
||||
pps->lookup_cookie = NULL;
|
||||
device_destroy(pps_class, pps->dev->devt);
|
||||
device_destroy(pps_class, pps->dev.devt);
|
||||
|
||||
/* Now we can release the ID for re-use */
|
||||
mutex_lock(&pps_idr_lock);
|
||||
idr_remove(&pps_idr, pps->id);
|
||||
put_device(&pps->dev);
|
||||
mutex_unlock(&pps_idr_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -427,6 +429,11 @@ void pps_unregister_cdev(struct pps_device *pps)
|
||||
* so that it will not be used again, even if the pps device cannot
|
||||
* be removed from the idr due to pending references holding the minor
|
||||
* number in use.
|
||||
*
|
||||
* Since pps_idr holds a reference to the device, the returned
|
||||
* pps_device is guaranteed to be valid until pps_unregister_cdev() is
|
||||
* called on it. But after calling pps_unregister_cdev(), it may be
|
||||
* freed at any time.
|
||||
*/
|
||||
struct pps_device *pps_lookup_dev(void const *cookie)
|
||||
{
|
||||
@@ -449,13 +456,11 @@ EXPORT_SYMBOL(pps_lookup_dev);
|
||||
static void __exit pps_exit(void)
|
||||
{
|
||||
class_destroy(pps_class);
|
||||
unregister_chrdev_region(pps_devt, PPS_MAX_SOURCES);
|
||||
__unregister_chrdev(pps_major, 0, PPS_MAX_SOURCES, "pps");
|
||||
}
|
||||
|
||||
static int __init pps_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
pps_class = class_create(THIS_MODULE, "pps");
|
||||
if (IS_ERR(pps_class)) {
|
||||
pr_err("failed to allocate class\n");
|
||||
@@ -463,8 +468,9 @@ static int __init pps_init(void)
|
||||
}
|
||||
pps_class->dev_groups = pps_groups;
|
||||
|
||||
err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
|
||||
if (err < 0) {
|
||||
pps_major = __register_chrdev(0, 0, PPS_MAX_SOURCES, "pps",
|
||||
&pps_cdev_fops);
|
||||
if (pps_major < 0) {
|
||||
pr_err("failed to allocate char device region\n");
|
||||
goto remove_class;
|
||||
}
|
||||
@@ -477,8 +483,7 @@ static int __init pps_init(void)
|
||||
|
||||
remove_class:
|
||||
class_destroy(pps_class);
|
||||
|
||||
return err;
|
||||
return pps_major;
|
||||
}
|
||||
|
||||
subsys_initcall(pps_init);
|
||||
|
||||
@@ -3589,7 +3589,7 @@ ptp_ocp_complete(struct ptp_ocp *bp)
|
||||
|
||||
pps = pps_lookup_dev(bp->ptp);
|
||||
if (pps)
|
||||
ptp_ocp_symlink(bp, pps->dev, "pps");
|
||||
ptp_ocp_symlink(bp, &pps->dev, "pps");
|
||||
|
||||
ptp_ocp_debugfs_add_device(bp);
|
||||
|
||||
|
||||
@@ -216,6 +216,7 @@ void ufs_bsg_remove(struct ufs_hba *hba)
|
||||
return;
|
||||
|
||||
bsg_remove_queue(hba->bsg_queue);
|
||||
hba->bsg_queue = NULL;
|
||||
|
||||
device_del(bsg_dev);
|
||||
put_device(bsg_dev);
|
||||
|
||||
@@ -2478,10 +2478,38 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
|
||||
{
|
||||
u32 reg;
|
||||
u32 timeout = 2000;
|
||||
u32 saved_config = 0;
|
||||
|
||||
if (pm_runtime_suspended(dwc->dev))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* When operating in USB 2.0 speeds (HS/FS), ensure that
|
||||
* GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY are cleared before starting
|
||||
* or stopping the controller. This resolves timeout issues that occur
|
||||
* during frequent role switches between host and device modes.
|
||||
*
|
||||
* Save and clear these settings, then restore them after completing the
|
||||
* controller start or stop sequence.
|
||||
*
|
||||
* This solution was discovered through experimentation as it is not
|
||||
* mentioned in the dwc3 programming guide. It has been tested on an
|
||||
* Exynos platforms.
|
||||
*/
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
|
||||
if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
|
||||
saved_config |= DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
|
||||
}
|
||||
|
||||
if (reg & DWC3_GUSB2PHYCFG_ENBLSLPM) {
|
||||
saved_config |= DWC3_GUSB2PHYCFG_ENBLSLPM;
|
||||
reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
|
||||
}
|
||||
|
||||
if (saved_config)
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||
if (is_on) {
|
||||
if (DWC3_VER_IS_WITHIN(DWC3, ANY, 187A)) {
|
||||
@@ -2509,6 +2537,12 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
|
||||
reg &= DWC3_DSTS_DEVCTRLHLT;
|
||||
} while (--timeout && !(!is_on ^ !reg));
|
||||
|
||||
if (saved_config) {
|
||||
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
|
||||
reg |= saved_config;
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||
}
|
||||
|
||||
if (!timeout)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/vfio.h>
|
||||
#include <linux/vgaarb.h>
|
||||
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||
|
||||
#include "vfio_pci_priv.h"
|
||||
|
||||
|
||||
@@ -432,8 +432,8 @@ static int __init omap_init_lcd_dma(void)
|
||||
|
||||
spin_lock_init(&lcd_dma.lock);
|
||||
|
||||
r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0,
|
||||
"LCD DMA", NULL);
|
||||
r = request_threaded_irq(INT_DMA_LCD, NULL, lcd_dma_irq_handler,
|
||||
IRQF_ONESHOT, "LCD DMA", NULL);
|
||||
if (r != 0)
|
||||
pr_err("unable to request IRQ for LCD DMA (error %d)\n", r);
|
||||
|
||||
|
||||
@@ -74,19 +74,21 @@ static inline phys_addr_t xen_dma_to_phys(struct device *dev,
|
||||
return xen_bus_to_phys(dev, dma_to_phys(dev, dma_addr));
|
||||
}
|
||||
|
||||
static inline bool range_requires_alignment(phys_addr_t p, size_t size)
|
||||
{
|
||||
phys_addr_t algn = 1ULL << (get_order(size) + PAGE_SHIFT);
|
||||
phys_addr_t bus_addr = pfn_to_bfn(XEN_PFN_DOWN(p)) << XEN_PAGE_SHIFT;
|
||||
|
||||
return IS_ALIGNED(p, algn) && !IS_ALIGNED(bus_addr, algn);
|
||||
}
|
||||
|
||||
static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
|
||||
{
|
||||
unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p);
|
||||
unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size);
|
||||
phys_addr_t algn = 1ULL << (get_order(size) + PAGE_SHIFT);
|
||||
|
||||
next_bfn = pfn_to_bfn(xen_pfn);
|
||||
|
||||
/* If buffer is physically aligned, ensure DMA alignment. */
|
||||
if (IS_ALIGNED(p, algn) &&
|
||||
!IS_ALIGNED((phys_addr_t)next_bfn << XEN_PAGE_SHIFT, algn))
|
||||
return 1;
|
||||
|
||||
for (i = 1; i < nr_pages; i++)
|
||||
if (pfn_to_bfn(++xen_pfn) != ++next_bfn)
|
||||
return 1;
|
||||
@@ -155,7 +157,8 @@ xen_swiotlb_alloc_coherent(struct device *dev, size_t size,
|
||||
|
||||
*dma_handle = xen_phys_to_dma(dev, phys);
|
||||
if (*dma_handle + size - 1 > dma_mask ||
|
||||
range_straddles_page_boundary(phys, size)) {
|
||||
range_straddles_page_boundary(phys, size) ||
|
||||
range_requires_alignment(phys, size)) {
|
||||
if (xen_create_contiguous_region(phys, order, fls64(dma_mask),
|
||||
dma_handle) != 0)
|
||||
goto out_free_pages;
|
||||
@@ -181,7 +184,8 @@ xen_swiotlb_free_coherent(struct device *dev, size_t size, void *vaddr,
|
||||
size = ALIGN(size, XEN_PAGE_SIZE);
|
||||
|
||||
if (WARN_ON_ONCE(dma_handle + size - 1 > dev->coherent_dma_mask) ||
|
||||
WARN_ON_ONCE(range_straddles_page_boundary(phys, size)))
|
||||
WARN_ON_ONCE(range_straddles_page_boundary(phys, size) ||
|
||||
range_requires_alignment(phys, size)))
|
||||
return;
|
||||
|
||||
if (TestClearPageXenRemapped(virt_to_page(vaddr)))
|
||||
|
||||
@@ -7387,8 +7387,6 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
if (orig_start)
|
||||
@@ -11370,6 +11368,8 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
|
||||
}
|
||||
|
||||
start += len;
|
||||
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
if (bsi.block_len)
|
||||
|
||||
@@ -84,6 +84,8 @@ out:
|
||||
fail:
|
||||
posix_acl_release(resp->acl_access);
|
||||
posix_acl_release(resp->acl_default);
|
||||
resp->acl_access = NULL;
|
||||
resp->acl_default = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,8 @@ out:
|
||||
fail:
|
||||
posix_acl_release(resp->acl_access);
|
||||
posix_acl_release(resp->acl_default);
|
||||
resp->acl_access = NULL;
|
||||
resp->acl_default = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -1410,8 +1410,11 @@ nfsd4_run_cb_work(struct work_struct *work)
|
||||
nfsd4_process_cb_update(cb);
|
||||
|
||||
clnt = clp->cl_cb_client;
|
||||
if (!clnt) {
|
||||
/* Callback channel broken, or client killed; give up: */
|
||||
if (!clnt || clp->cl_state == NFSD4_COURTESY) {
|
||||
/*
|
||||
* Callback channel broken, client killed or
|
||||
* nfs4_client in courtesy state; give up.
|
||||
*/
|
||||
nfsd41_destroy_cb(cb);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -393,9 +393,9 @@ static ssize_t orangefs_debug_write(struct file *file,
|
||||
* Thwart users who try to jamb a ridiculous number
|
||||
* of bytes into the debug file...
|
||||
*/
|
||||
if (count > ORANGEFS_MAX_DEBUG_STRING_LEN + 1) {
|
||||
if (count > ORANGEFS_MAX_DEBUG_STRING_LEN) {
|
||||
silly = count;
|
||||
count = ORANGEFS_MAX_DEBUG_STRING_LEN + 1;
|
||||
count = ORANGEFS_MAX_DEBUG_STRING_LEN;
|
||||
}
|
||||
|
||||
buf = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL);
|
||||
|
||||
@@ -56,8 +56,7 @@ struct pps_device {
|
||||
|
||||
unsigned int id; /* PPS source unique ID */
|
||||
void const *lookup_cookie; /* For pps_lookup_dev() only */
|
||||
struct cdev cdev;
|
||||
struct device *dev;
|
||||
struct device dev;
|
||||
struct fasync_struct *async_queue; /* fasync method */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
@@ -198,10 +198,12 @@ struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto)
|
||||
if (netif_is_l3_slave(dev)) {
|
||||
struct net_device *master;
|
||||
|
||||
rcu_read_lock();
|
||||
master = netdev_master_upper_dev_get_rcu(dev);
|
||||
if (master && master->l3mdev_ops->l3mdev_l3_out)
|
||||
skb = master->l3mdev_ops->l3mdev_l3_out(master, sk,
|
||||
skb, proto);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
return skb;
|
||||
|
||||
@@ -461,7 +461,6 @@ static void root_cgroup_cputime(struct cgroup_base_stat *bstat)
|
||||
|
||||
cputime->sum_exec_runtime += user;
|
||||
cputime->sum_exec_runtime += sys;
|
||||
cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL];
|
||||
|
||||
#ifdef CONFIG_SCHED_CORE
|
||||
bstat->forceidle_sum += cpustat[CPUTIME_FORCEIDLE];
|
||||
|
||||
@@ -685,6 +685,15 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
|
||||
break;
|
||||
}
|
||||
|
||||
if (ax25->ax25_dev) {
|
||||
if (dev == ax25->ax25_dev->dev) {
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
}
|
||||
netdev_put(ax25->ax25_dev->dev, &ax25->dev_tracker);
|
||||
ax25_dev_put(ax25->ax25_dev);
|
||||
}
|
||||
|
||||
ax25->ax25_dev = ax25_dev_ax25dev(dev);
|
||||
if (!ax25->ax25_dev) {
|
||||
rcu_read_unlock();
|
||||
@@ -692,6 +701,8 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
|
||||
break;
|
||||
}
|
||||
ax25_fillin_cb(ax25, ax25->ax25_dev);
|
||||
netdev_hold(dev, &ax25->dev_tracker, GFP_ATOMIC);
|
||||
ax25_dev_hold(ax25->ax25_dev);
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
|
||||
|
||||
@@ -113,8 +113,6 @@ static void
|
||||
batadv_v_hardif_neigh_init(struct batadv_hardif_neigh_node *hardif_neigh)
|
||||
{
|
||||
ewma_throughput_init(&hardif_neigh->bat_v.throughput);
|
||||
INIT_WORK(&hardif_neigh->bat_v.metric_work,
|
||||
batadv_v_elp_throughput_metric_update);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/nl80211.h>
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
@@ -42,6 +44,18 @@
|
||||
#include "routing.h"
|
||||
#include "send.h"
|
||||
|
||||
/**
|
||||
* struct batadv_v_metric_queue_entry - list of hardif neighbors which require
|
||||
* and metric update
|
||||
*/
|
||||
struct batadv_v_metric_queue_entry {
|
||||
/** @hardif_neigh: hardif neighbor scheduled for metric update */
|
||||
struct batadv_hardif_neigh_node *hardif_neigh;
|
||||
|
||||
/** @list: list node for metric_queue */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* batadv_v_elp_start_timer() - restart timer for ELP periodic work
|
||||
* @hard_iface: the interface for which the timer has to be reset
|
||||
@@ -60,25 +74,36 @@ static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
|
||||
/**
|
||||
* batadv_v_elp_get_throughput() - get the throughput towards a neighbour
|
||||
* @neigh: the neighbour for which the throughput has to be obtained
|
||||
* @pthroughput: calculated throughput towards the given neighbour in multiples
|
||||
* of 100kpbs (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
|
||||
*
|
||||
* Return: The throughput towards the given neighbour in multiples of 100kpbs
|
||||
* (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
|
||||
* Return: true when value behind @pthroughput was set
|
||||
*/
|
||||
static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
||||
static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
|
||||
u32 *pthroughput)
|
||||
{
|
||||
struct batadv_hard_iface *hard_iface = neigh->if_incoming;
|
||||
struct net_device *soft_iface = hard_iface->soft_iface;
|
||||
struct ethtool_link_ksettings link_settings;
|
||||
struct net_device *real_netdev;
|
||||
struct station_info sinfo;
|
||||
u32 throughput;
|
||||
int ret;
|
||||
|
||||
/* don't query throughput when no longer associated with any
|
||||
* batman-adv interface
|
||||
*/
|
||||
if (!soft_iface)
|
||||
return false;
|
||||
|
||||
/* if the user specified a customised value for this interface, then
|
||||
* return it directly
|
||||
*/
|
||||
throughput = atomic_read(&hard_iface->bat_v.throughput_override);
|
||||
if (throughput != 0)
|
||||
return throughput;
|
||||
if (throughput != 0) {
|
||||
*pthroughput = throughput;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* if this is a wireless device, then ask its throughput through
|
||||
* cfg80211 API
|
||||
@@ -105,27 +130,39 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
||||
* possible to delete this neighbor. For now set
|
||||
* the throughput metric to 0.
|
||||
*/
|
||||
return 0;
|
||||
*pthroughput = 0;
|
||||
return true;
|
||||
}
|
||||
if (ret)
|
||||
goto default_throughput;
|
||||
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))
|
||||
return sinfo.expected_throughput / 100;
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)) {
|
||||
*pthroughput = sinfo.expected_throughput / 100;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* try to estimate the expected throughput based on reported tx
|
||||
* rates
|
||||
*/
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
|
||||
return cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
|
||||
*pthroughput = cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
goto default_throughput;
|
||||
}
|
||||
|
||||
/* only use rtnl_trylock because the elp worker will be cancelled while
|
||||
* the rntl_lock is held. the cancel_delayed_work_sync() would otherwise
|
||||
* wait forever when the elp work_item was started and it is then also
|
||||
* trying to rtnl_lock
|
||||
*/
|
||||
if (!rtnl_trylock())
|
||||
return false;
|
||||
|
||||
/* if not a wifi interface, check if this device provides data via
|
||||
* ethtool (e.g. an Ethernet adapter)
|
||||
*/
|
||||
rtnl_lock();
|
||||
ret = __ethtool_get_link_ksettings(hard_iface->net_dev, &link_settings);
|
||||
rtnl_unlock();
|
||||
if (ret == 0) {
|
||||
@@ -136,13 +173,15 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
||||
hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
|
||||
|
||||
throughput = link_settings.base.speed;
|
||||
if (throughput && throughput != SPEED_UNKNOWN)
|
||||
return throughput * 10;
|
||||
if (throughput && throughput != SPEED_UNKNOWN) {
|
||||
*pthroughput = throughput * 10;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
default_throughput:
|
||||
if (!(hard_iface->bat_v.flags & BATADV_WARNING_DEFAULT)) {
|
||||
batadv_info(hard_iface->soft_iface,
|
||||
batadv_info(soft_iface,
|
||||
"WiFi driver or ethtool info does not provide information about link speeds on interface %s, therefore defaulting to hardcoded throughput values of %u.%1u Mbps. Consider overriding the throughput manually or checking your driver.\n",
|
||||
hard_iface->net_dev->name,
|
||||
BATADV_THROUGHPUT_DEFAULT_VALUE / 10,
|
||||
@@ -151,31 +190,26 @@ default_throughput:
|
||||
}
|
||||
|
||||
/* if none of the above cases apply, return the base_throughput */
|
||||
return BATADV_THROUGHPUT_DEFAULT_VALUE;
|
||||
*pthroughput = BATADV_THROUGHPUT_DEFAULT_VALUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* batadv_v_elp_throughput_metric_update() - worker updating the throughput
|
||||
* metric of a single hop neighbour
|
||||
* @work: the work queue item
|
||||
* @neigh: the neighbour to probe
|
||||
*/
|
||||
void batadv_v_elp_throughput_metric_update(struct work_struct *work)
|
||||
static void
|
||||
batadv_v_elp_throughput_metric_update(struct batadv_hardif_neigh_node *neigh)
|
||||
{
|
||||
struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
|
||||
struct batadv_hardif_neigh_node *neigh;
|
||||
u32 throughput;
|
||||
bool valid;
|
||||
|
||||
neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
|
||||
metric_work);
|
||||
neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
|
||||
bat_v);
|
||||
valid = batadv_v_elp_get_throughput(neigh, &throughput);
|
||||
if (!valid)
|
||||
return;
|
||||
|
||||
ewma_throughput_add(&neigh->bat_v.throughput,
|
||||
batadv_v_elp_get_throughput(neigh));
|
||||
|
||||
/* decrement refcounter to balance increment performed before scheduling
|
||||
* this task
|
||||
*/
|
||||
batadv_hardif_neigh_put(neigh);
|
||||
ewma_throughput_add(&neigh->bat_v.throughput, throughput);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,14 +283,16 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
|
||||
*/
|
||||
static void batadv_v_elp_periodic_work(struct work_struct *work)
|
||||
{
|
||||
struct batadv_v_metric_queue_entry *metric_entry;
|
||||
struct batadv_v_metric_queue_entry *metric_safe;
|
||||
struct batadv_hardif_neigh_node *hardif_neigh;
|
||||
struct batadv_hard_iface *hard_iface;
|
||||
struct batadv_hard_iface_bat_v *bat_v;
|
||||
struct batadv_elp_packet *elp_packet;
|
||||
struct list_head metric_queue;
|
||||
struct batadv_priv *bat_priv;
|
||||
struct sk_buff *skb;
|
||||
u32 elp_interval;
|
||||
bool ret;
|
||||
|
||||
bat_v = container_of(work, struct batadv_hard_iface_bat_v, elp_wq.work);
|
||||
hard_iface = container_of(bat_v, struct batadv_hard_iface, bat_v);
|
||||
@@ -292,6 +328,8 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
|
||||
|
||||
atomic_inc(&hard_iface->bat_v.elp_seqno);
|
||||
|
||||
INIT_LIST_HEAD(&metric_queue);
|
||||
|
||||
/* The throughput metric is updated on each sent packet. This way, if a
|
||||
* node is dead and no longer sends packets, batman-adv is still able to
|
||||
* react timely to its death.
|
||||
@@ -316,16 +354,28 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
|
||||
|
||||
/* Reading the estimated throughput from cfg80211 is a task that
|
||||
* may sleep and that is not allowed in an rcu protected
|
||||
* context. Therefore schedule a task for that.
|
||||
* context. Therefore add it to metric_queue and process it
|
||||
* outside rcu protected context.
|
||||
*/
|
||||
ret = queue_work(batadv_event_workqueue,
|
||||
&hardif_neigh->bat_v.metric_work);
|
||||
|
||||
if (!ret)
|
||||
metric_entry = kzalloc(sizeof(*metric_entry), GFP_ATOMIC);
|
||||
if (!metric_entry) {
|
||||
batadv_hardif_neigh_put(hardif_neigh);
|
||||
continue;
|
||||
}
|
||||
|
||||
metric_entry->hardif_neigh = hardif_neigh;
|
||||
list_add(&metric_entry->list, &metric_queue);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
list_for_each_entry_safe(metric_entry, metric_safe, &metric_queue, list) {
|
||||
batadv_v_elp_throughput_metric_update(metric_entry->hardif_neigh);
|
||||
|
||||
batadv_hardif_neigh_put(metric_entry->hardif_neigh);
|
||||
list_del(&metric_entry->list);
|
||||
kfree(metric_entry);
|
||||
}
|
||||
|
||||
restart_timer:
|
||||
batadv_v_elp_start_timer(hard_iface);
|
||||
out:
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "main.h"
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface);
|
||||
void batadv_v_elp_iface_disable(struct batadv_hard_iface *hard_iface);
|
||||
@@ -19,6 +18,5 @@ void batadv_v_elp_iface_activate(struct batadv_hard_iface *primary_iface,
|
||||
void batadv_v_elp_primary_iface_set(struct batadv_hard_iface *primary_iface);
|
||||
int batadv_v_elp_packet_recv(struct sk_buff *skb,
|
||||
struct batadv_hard_iface *if_incoming);
|
||||
void batadv_v_elp_throughput_metric_update(struct work_struct *work);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_BAT_V_ELP_H_ */
|
||||
|
||||
@@ -596,9 +596,6 @@ struct batadv_hardif_neigh_node_bat_v {
|
||||
* neighbor
|
||||
*/
|
||||
unsigned long last_unicast_tx;
|
||||
|
||||
/** @metric_work: work queue callback item for metric update */
|
||||
struct work_struct metric_work;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1684,7 +1684,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
|
||||
bool ret;
|
||||
|
||||
if (netif_is_l3_master(skb->dev)) {
|
||||
dev = __dev_get_by_index(dev_net(skb->dev), IPCB(skb)->iif);
|
||||
dev = dev_get_by_index_rcu(dev_net(skb->dev), IPCB(skb)->iif);
|
||||
if (!dev)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1122,7 +1122,22 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
||||
BYT_RT5640_SSP0_AIF2 |
|
||||
BYT_RT5640_MCLK_EN),
|
||||
},
|
||||
{ /* Vexia Edu Atla 10 tablet */
|
||||
{
|
||||
/* Vexia Edu Atla 10 tablet 5V version */
|
||||
.matches = {
|
||||
/* Having all 3 of these not set is somewhat unique */
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "To be filled by O.E.M."),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "To be filled by O.E.M."),
|
||||
/* Above strings are too generic, also match on BIOS date */
|
||||
DMI_MATCH(DMI_BIOS_DATE, "05/14/2015"),
|
||||
},
|
||||
.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
|
||||
BYT_RT5640_JD_NOT_INV |
|
||||
BYT_RT5640_SSP0_AIF1 |
|
||||
BYT_RT5640_MCLK_EN),
|
||||
},
|
||||
{ /* Vexia Edu Atla 10 tablet 9V version */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
|
||||
|
||||
@@ -46,12 +46,6 @@ remove_chip() {
|
||||
rmdir $CONFIGFS_DIR/$CHIP || fail "Unable to remove the chip"
|
||||
}
|
||||
|
||||
configfs_cleanup() {
|
||||
for CHIP in `ls $CONFIGFS_DIR/`; do
|
||||
remove_chip $CHIP
|
||||
done
|
||||
}
|
||||
|
||||
create_chip() {
|
||||
local CHIP=$1
|
||||
|
||||
@@ -105,6 +99,13 @@ disable_chip() {
|
||||
echo 0 > $CONFIGFS_DIR/$CHIP/live || fail "Unable to disable the chip"
|
||||
}
|
||||
|
||||
configfs_cleanup() {
|
||||
for CHIP in `ls $CONFIGFS_DIR/`; do
|
||||
disable_chip $CHIP
|
||||
remove_chip $CHIP
|
||||
done
|
||||
}
|
||||
|
||||
configfs_chip_name() {
|
||||
local CHIP=$1
|
||||
local BANK=$2
|
||||
@@ -181,6 +182,7 @@ create_chip chip
|
||||
create_bank chip bank
|
||||
enable_chip chip
|
||||
test -n `cat $CONFIGFS_DIR/chip/bank/chip_name` || fail "chip_name doesn't work"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "1.2. chip_name returns 'none' if the chip is still pending"
|
||||
@@ -195,6 +197,7 @@ create_chip chip
|
||||
create_bank chip bank
|
||||
enable_chip chip
|
||||
test -n `cat $CONFIGFS_DIR/chip/dev_name` || fail "dev_name doesn't work"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2. Creating and configuring simulated chips"
|
||||
@@ -204,6 +207,7 @@ create_chip chip
|
||||
create_bank chip bank
|
||||
enable_chip chip
|
||||
test "`get_chip_num_lines chip bank`" = "1" || fail "default number of lines is not 1"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2.2. Number of lines can be specified"
|
||||
@@ -212,6 +216,7 @@ create_bank chip bank
|
||||
set_num_lines chip bank 16
|
||||
enable_chip chip
|
||||
test "`get_chip_num_lines chip bank`" = "16" || fail "number of lines is not 16"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2.3. Label can be set"
|
||||
@@ -220,6 +225,7 @@ create_bank chip bank
|
||||
set_label chip bank foobar
|
||||
enable_chip chip
|
||||
test "`get_chip_label chip bank`" = "foobar" || fail "label is incorrect"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2.4. Label can be left empty"
|
||||
@@ -227,6 +233,7 @@ create_chip chip
|
||||
create_bank chip bank
|
||||
enable_chip chip
|
||||
test -z "`cat $CONFIGFS_DIR/chip/bank/label`" || fail "label is not empty"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2.5. Line names can be configured"
|
||||
@@ -238,6 +245,7 @@ set_line_name chip bank 2 bar
|
||||
enable_chip chip
|
||||
test "`get_line_name chip bank 0`" = "foo" || fail "line name is incorrect"
|
||||
test "`get_line_name chip bank 2`" = "bar" || fail "line name is incorrect"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2.6. Line config can remain unused if offset is greater than number of lines"
|
||||
@@ -248,6 +256,7 @@ set_line_name chip bank 5 foobar
|
||||
enable_chip chip
|
||||
test "`get_line_name chip bank 0`" = "" || fail "line name is incorrect"
|
||||
test "`get_line_name chip bank 1`" = "" || fail "line name is incorrect"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2.7. Line configfs directory names are sanitized"
|
||||
@@ -267,6 +276,7 @@ for CHIP in $CHIPS; do
|
||||
enable_chip $CHIP
|
||||
done
|
||||
for CHIP in $CHIPS; do
|
||||
disable_chip $CHIP
|
||||
remove_chip $CHIP
|
||||
done
|
||||
|
||||
@@ -278,6 +288,7 @@ echo foobar > $CONFIGFS_DIR/chip/bank/label 2> /dev/null && \
|
||||
fail "Setting label of a live chip should fail"
|
||||
echo 8 > $CONFIGFS_DIR/chip/bank/num_lines 2> /dev/null && \
|
||||
fail "Setting number of lines of a live chip should fail"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2.10. Can't create line items when chip is live"
|
||||
@@ -285,6 +296,7 @@ create_chip chip
|
||||
create_bank chip bank
|
||||
enable_chip chip
|
||||
mkdir $CONFIGFS_DIR/chip/bank/line0 2> /dev/null && fail "Creating line item should fail"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "2.11. Probe errors are propagated to user-space"
|
||||
@@ -316,6 +328,7 @@ mkdir -p $CONFIGFS_DIR/chip/bank/line4/hog
|
||||
enable_chip chip
|
||||
$BASE_DIR/gpio-mockup-cdev -s 1 /dev/`configfs_chip_name chip bank` 4 2> /dev/null && \
|
||||
fail "Setting the value of a hogged line shouldn't succeed"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "3. Controlling simulated chips"
|
||||
@@ -331,6 +344,7 @@ test "$?" = "1" || fail "pull set incorrectly"
|
||||
sysfs_set_pull chip bank 0 pull-down
|
||||
$BASE_DIR/gpio-mockup-cdev /dev/`configfs_chip_name chip bank` 1
|
||||
test "$?" = "0" || fail "pull set incorrectly"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "3.2. Pull can be read from sysfs"
|
||||
@@ -344,6 +358,7 @@ SYSFS_PATH=/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/pull
|
||||
test `cat $SYSFS_PATH` = "pull-down" || fail "reading the pull failed"
|
||||
sysfs_set_pull chip bank 0 pull-up
|
||||
test `cat $SYSFS_PATH` = "pull-up" || fail "reading the pull failed"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "3.3. Incorrect input in sysfs is rejected"
|
||||
@@ -355,6 +370,7 @@ DEVNAME=`configfs_dev_name chip`
|
||||
CHIPNAME=`configfs_chip_name chip bank`
|
||||
SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/pull"
|
||||
echo foobar > $SYSFS_PATH 2> /dev/null && fail "invalid input not detected"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "3.4. Can't write to value"
|
||||
@@ -365,6 +381,7 @@ DEVNAME=`configfs_dev_name chip`
|
||||
CHIPNAME=`configfs_chip_name chip bank`
|
||||
SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
|
||||
echo 1 > $SYSFS_PATH 2> /dev/null && fail "writing to 'value' succeeded unexpectedly"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "4. Simulated GPIO chips are functional"
|
||||
@@ -382,6 +399,7 @@ $BASE_DIR/gpio-mockup-cdev -s 1 /dev/`configfs_chip_name chip bank` 0 &
|
||||
sleep 0.1 # FIXME Any better way?
|
||||
test `cat $SYSFS_PATH` = "1" || fail "incorrect value read from sysfs"
|
||||
kill $!
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "4.2. Bias settings work correctly"
|
||||
@@ -394,6 +412,7 @@ CHIPNAME=`configfs_chip_name chip bank`
|
||||
SYSFS_PATH="/sys/devices/platform/$DEVNAME/$CHIPNAME/sim_gpio0/value"
|
||||
$BASE_DIR/gpio-mockup-cdev -b pull-up /dev/`configfs_chip_name chip bank` 0
|
||||
test `cat $SYSFS_PATH` = "1" || fail "bias setting does not work"
|
||||
disable_chip chip
|
||||
remove_chip chip
|
||||
|
||||
echo "GPIO $MODULE test PASS"
|
||||
|
||||
@@ -786,6 +786,14 @@ static int stop_tracing;
|
||||
static struct trace_instance *hist_inst = NULL;
|
||||
static void stop_hist(int sig)
|
||||
{
|
||||
if (stop_tracing) {
|
||||
/*
|
||||
* Stop requested twice in a row; abort event processing and
|
||||
* exit immediately
|
||||
*/
|
||||
tracefs_iterate_stop(hist_inst->inst);
|
||||
return;
|
||||
}
|
||||
stop_tracing = 1;
|
||||
if (hist_inst)
|
||||
trace_instance_stop(hist_inst);
|
||||
|
||||
@@ -578,6 +578,14 @@ static int stop_tracing;
|
||||
static struct trace_instance *top_inst = NULL;
|
||||
static void stop_top(int sig)
|
||||
{
|
||||
if (stop_tracing) {
|
||||
/*
|
||||
* Stop requested twice in a row; abort event processing and
|
||||
* exit immediately
|
||||
*/
|
||||
tracefs_iterate_stop(top_inst->inst);
|
||||
return;
|
||||
}
|
||||
stop_tracing = 1;
|
||||
if (top_inst)
|
||||
trace_instance_stop(top_inst);
|
||||
|
||||
Reference in New Issue
Block a user