* Fix S390_USER_OPEREXEC so it can now be enabled regardless of other
  unrelated capabilities

* Fix handling of the _PAGE_UNUSED pte bit that could lead to guest
  memory corruption in some scenarios

* A bunch of misc gmap fixes (locking, behaviour under memory pressure)

* Fix CMMA dirty tracking
This commit is contained in:
Paolo Bonzini
2026-06-24 13:40:39 +02:00
165 changed files with 1615 additions and 752 deletions

View File

@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: GPIO-based I2C Bus Mux
maintainers:
- Wolfram Sang <wsa@kernel.org>
- Peter Korsgaard <peter.korsgaard@barco.com>
description: |
This binding describes an I2C bus multiplexer that uses GPIOs to route the I2C signals.

View File

@@ -6840,7 +6840,7 @@ s390 specific.
} s390_ucontrol;
s390 specific. A page fault has occurred for a user controlled virtual
machine (KVM_VM_S390_UNCONTROL) on its host page table that cannot be
machine (KVM_VM_S390_UCONTROL) on its host page table that cannot be
resolved by the kernel.
The program code and the translation exception code that were placed
in the cpu's lowcore are presented here as defined by the z Architecture

View File

@@ -10772,6 +10772,7 @@ GENERIC GPIO I2C MULTIPLEXER DRIVER
M: Peter Korsgaard <peter.korsgaard@barco.com>
L: linux-i2c@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/i2c/i2c-mux-gpio.yaml
F: Documentation/i2c/muxes/i2c-mux-gpio.rst
F: drivers/i2c/muxes/i2c-mux-gpio.c
F: include/linux/platform_data/i2c-mux-gpio.h
@@ -12094,11 +12095,11 @@ F: Documentation/i2c/busses/i2c-parport.rst
F: drivers/i2c/busses/i2c-parport.c
I2C SUBSYSTEM
M: Wolfram Sang <wsa+renesas@sang-engineering.com>
M: Andi Shyti <andi.shyti@kernel.org>
L: linux-i2c@vger.kernel.org
S: Maintained
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git
F: Documentation/i2c/
F: drivers/i2c/*
F: include/dt-bindings/i2c/i2c.h
@@ -20550,6 +20551,7 @@ PCI ENDPOINT SUBSYSTEM
M: Manivannan Sadhasivam <mani@kernel.org>
M: Krzysztof Wilczyński <kwilczynski@kernel.org>
R: Kishon Vijay Abraham I <kishon@kernel.org>
R: Frank Li <Frank.Li@kernel.org>
L: linux-pci@vger.kernel.org
S: Supported
Q: https://patchwork.kernel.org/project/linux-pci/list/
@@ -25926,7 +25928,6 @@ F: drivers/media/platform/synopsys/hdmirx/*
SYNOPSYS DESIGNWARE I2C DRIVER
M: Mika Westerberg <mika.westerberg@linux.intel.com>
R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
R: Jan Dabros <jsd@semihalf.com>
L: linux-i2c@vger.kernel.org
S: Supported
F: drivers/i2c/busses/i2c-designware-*

View File

@@ -2,7 +2,7 @@
VERSION = 7
PATCHLEVEL = 1
SUBLEVEL = 0
EXTRAVERSION = -rc7
EXTRAVERSION =
NAME = Baby Opossum Posse
# *DOCUMENTATION*

View File

@@ -56,8 +56,19 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen);
* the bus. Rather than special-case the machine, just let the compiler
* generate the access for CPUs prior to ARMv6.
*/
#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
#define __raw_writew(v,a) ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
#define __raw_writew __raw_writew
static __no_kasan_or_inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
__chk_io_ptr(addr);
*(volatile unsigned short __force *)addr = val;
}
#define __raw_readw __raw_readw
static __no_kasan_or_inline u16 __raw_readw(const volatile void __iomem *addr)
{
__chk_io_ptr(addr);
return *(const volatile unsigned short __force *)addr;
}
#else
/*
* When running under a hypervisor, we want to avoid I/O accesses with

View File

@@ -567,7 +567,7 @@ ENTRY(__switch_to)
@ are using KASAN
mov_l r2, KASAN_SHADOW_OFFSET
add r2, r2, ip, lsr #KASAN_SHADOW_SCALE_SHIFT
ldr r2, [r2]
ldrb r2, [r2]
#endif
#endif

View File

@@ -21,6 +21,7 @@
#include <asm/suspend.h>
#include <asm/page.h>
#include <asm/sections.h>
#include <asm/uaccess.h>
#include "reboot.h"
int pfn_is_nosave(unsigned long pfn)
@@ -82,6 +83,15 @@ static void notrace arch_restore_image(void *unused)
{
struct pbe *pbe;
/*
* With CONFIG_CPU_TTBR0_PAN enabled, TTBCR.EPD0 is set to block
* TTBR0 page-table walks. The identity mapping used here lives at
* low (user-space) virtual addresses and is only reachable via
* TTBR0, so re-enable those walks before switching page tables.
* On non-PAN kernels this is a no-op.
*/
if (IS_ENABLED(CONFIG_CPU_TTBR0_PAN))
uaccess_save_and_enable();
cpu_switch_mm(idmap_pgd, &init_mm);
for (pbe = restore_pblist; pbe; pbe = pbe->next)
copy_page(pbe->orig_address, pbe->address);

View File

@@ -34,6 +34,7 @@ static int ncores;
static struct regmap *pmu;
static int has_pmu = true;
static struct reset_control *cpu_rstc[4];
static int pmu_power_domain_is_on(int pd)
{
@@ -64,9 +65,11 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
static int pmu_set_power_domain(int pd, bool on)
{
u32 val = (on) ? 0 : BIT(pd);
struct reset_control *rstc = rockchip_get_core_reset(pd);
struct reset_control *rstc;
int ret;
rstc = pd < ARRAY_SIZE(cpu_rstc) ? cpu_rstc[pd] : ERR_PTR(-EINVAL);
if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
pr_err("%s: could not get reset control for core %d\n",
__func__, pd);
@@ -100,11 +103,8 @@ static int pmu_set_power_domain(int pd, bool on)
}
}
if (!IS_ERR(rstc)) {
if (on)
reset_control_deassert(rstc);
reset_control_put(rstc);
}
if (!IS_ERR(rstc) && on)
reset_control_deassert(rstc);
return 0;
}
@@ -312,6 +312,10 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
ncores = ((l2ctlr >> 24) & 0x3) + 1;
}
/* Collect cpu core reset control for each core */
for (i = 0; i < ncores; i++)
cpu_rstc[i] = rockchip_get_core_reset(i);
/* Make sure that all cores except the first are really off */
for (i = 1; i < ncores; i++)
pmu_set_power_domain(0 + i, false);

View File

@@ -11,6 +11,7 @@
#include <asm/pgalloc.h>
#include <asm/sections.h>
#include <asm/system_info.h>
#include <asm/uaccess.h>
/*
* Note: accesses outside of the kernel image and the identity map area
@@ -133,6 +134,17 @@ early_initcall(init_static_idmap);
*/
void setup_mm_for_reboot(void)
{
/*
* With CONFIG_CPU_TTBR0_PAN enabled, TTBCR.EPD0 is set whenever
* user-space access is disabled in order to block TTBR0 page-table
* walks. The identity mapping lives at low (user-space) virtual
* addresses and can only be reached via TTBR0, so we must re-enable
* those walks before switching page tables. On non-PAN kernels this
* is a no-op.
*/
if (IS_ENABLED(CONFIG_CPU_TTBR0_PAN))
uaccess_save_and_enable();
/* Switch to the identity mapping. */
cpu_switch_mm(idmap_pgd, &init_mm);
local_flush_bp_all();

View File

@@ -29,9 +29,6 @@ config GENERIC_BUG
config GENERIC_BUG_RELATIVE_POINTERS
def_bool y
config GENERIC_LOCKBREAK
def_bool y if PREEMPTION
config AUDIT_ARCH
def_bool y

View File

@@ -980,6 +980,8 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
static inline void set_pte(pte_t *ptep, pte_t pte)
{
if (pte_present(pte))
pte = clear_pte_bit(pte, __pgprot(_PAGE_UNUSED));
WRITE_ONCE(*ptep, pte);
}
@@ -1332,8 +1334,6 @@ pgprot_t pgprot_writecombine(pgprot_t prot);
static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t entry, unsigned int nr)
{
if (pte_present(entry))
entry = clear_pte_bit(entry, __pgprot(_PAGE_UNUSED));
page_table_check_ptes_set(mm, addr, ptep, entry, nr);
for (;;) {
set_pte(ptep, entry);

View File

@@ -1209,7 +1209,7 @@ int dat_peek_cmma(gfn_t start, union asce asce, unsigned int *count, u8 *values)
int rc;
rc = _dat_walk_gfn_range(start, start + *count, asce, &ops, DAT_WALK_DEFAULT, &state);
*count = state.end - start;
*count = state.end >= start ? state.end - start : 0;
/* Return success if at least one value was saved, otherwise an error. */
return (rc == -EFAULT && *count > 0) ? 0 : rc;
}
@@ -1253,6 +1253,9 @@ int dat_get_cmma(union asce asce, gfn_t *start, unsigned int *count, u8 *values,
};
_dat_walk_gfn_range(*start, asce_end(asce), asce, &ops, DAT_WALK_IGN_HOLES, &state);
/* If no dirty pages were found, wrap around and continue searching */
if (*start && state.start == -1)
_dat_walk_gfn_range(0, *start, asce, &ops, DAT_WALK_IGN_HOLES, &state);
if (state.start == -1) {
*count = 0;

View File

@@ -332,7 +332,7 @@ static long gmap_clear_young_crste(union crste *crstep, gfn_t gfn, gfn_t end, st
new.h.i = 1;
new.s.fc1.y = 0;
new.s.fc1.prefix_notif = 0;
if (new.s.fc1.d || !new.h.p)
if ((new.s.fc1.d || !new.h.p) && !new.s.fc1.s)
folio_set_dirty(phys_to_folio(crste_origin_large(crste)));
new.s.fc1.d = 0;
new.h.p = 1;
@@ -1098,23 +1098,46 @@ int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gf
return 0;
}
static long __set_cmma_dirty_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
static long __set_cmma_clean_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
{
__atomic64_or(PGSTE_CMMA_D_BIT, &pgste_of(ptep)->val);
union pgste pgste;
pgste = pgste_get_lock(ptep);
pgste.cmma_d = 0;
pgste_set_unlock(ptep, pgste);
if (need_resched())
return next;
return 0;
}
void gmap_set_cmma_all_dirty(struct gmap *gmap)
static long __set_cmma_dirty_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
{
const struct dat_walk_ops ops = { .pte_entry = __set_cmma_dirty_pte, };
union pgste pgste;
pgste = pgste_get_lock(ptep);
if (!pgste.cmma_d)
atomic64_inc(walk->priv);
pgste.cmma_d = 1;
pgste_set_unlock(ptep, pgste);
if (need_resched())
return next;
return 0;
}
void _gmap_set_cmma_all(struct gmap *gmap, bool dirty)
{
const struct dat_walk_ops ops = {
.pte_entry = dirty ? __set_cmma_dirty_pte : __set_cmma_clean_pte,
};
gfn_t gfn = 0;
do {
scoped_guard(read_lock, &gmap->kvm->mmu_lock)
gfn = _dat_walk_gfn_range(gfn, asce_end(gmap->asce), gmap->asce, &ops,
DAT_WALK_IGN_HOLES, NULL);
DAT_WALK_IGN_HOLES,
&gmap->kvm->arch.cmma_dirty_pages);
cond_resched();
} while (gfn);
}
@@ -1287,7 +1310,7 @@ static int gmap_protect_asce_top_level(struct kvm_s390_mmu_cache *mc, struct gma
/* Pairs with the smp_wmb() in kvm_mmu_invalidate_end(). */
smp_rmb();
rc = kvm_s390_get_guest_pages(sg->kvm, context.f, asce.rsto, asce.dt + 1, false);
rc = kvm_s390_get_guest_pages(sg->kvm, context.f, asce.rsto, asce.tl + 1, false);
if (rc > 0)
rc = -EFAULT;
if (!rc)

View File

@@ -104,7 +104,7 @@ int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn
gfn_t r_gfn, int level);
int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn,
kvm_pfn_t pfn, int level, bool wr);
void gmap_set_cmma_all_dirty(struct gmap *gmap);
void _gmap_set_cmma_all(struct gmap *gmap, bool dirty);
void _gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn);
struct gmap *gmap_create_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *gmap,
union asce asce, int edat_level);
@@ -198,6 +198,16 @@ static inline bool pte_needs_unshadow(union pte oldpte, union pte newpte, union
return !newpte.h.p || !newpte.s.pr;
}
static inline void gmap_set_cmma_all_dirty(struct gmap *gmap)
{
_gmap_set_cmma_all(gmap, true);
}
static inline void gmap_set_cmma_all_clean(struct gmap *gmap)
{
_gmap_set_cmma_all(gmap, false);
}
static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, union pte newpte,
union pgste pgste, gfn_t gfn, bool needs_lock)
{

View File

@@ -1022,9 +1022,11 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
if (!kvm->arch.use_cmma)
break;
guard(mutex)(&kvm->lock);
VM_EVENT(kvm, 3, "%s", "RESET: CMMA states");
do {
start_gfn = dat_reset_cmma(kvm->arch.gmap->asce, start_gfn);
scoped_guard(read_lock, &kvm->mmu_lock)
start_gfn = dat_reset_cmma(kvm->arch.gmap->asce, start_gfn);
cond_resched();
} while (start_gfn);
ret = 0;
@@ -1217,13 +1219,13 @@ static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
/*
* Must be called with kvm->srcu held to avoid races on memslots, and with
* kvm->slots_lock to avoid races with ourselves and kvm_s390_vm_stop_migration.
* kvm->slots_lock to avoid races with ourselves, kvm_s390_vm_stop_migration(),
* and kvm_s390_get_cmma_bits().
*/
static int kvm_s390_vm_start_migration(struct kvm *kvm)
{
struct kvm_memory_slot *ms;
struct kvm_memslots *slots;
unsigned long ram_pages = 0;
int bkt;
/* migration mode already enabled */
@@ -1240,28 +1242,54 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
kvm_for_each_memslot(ms, bkt, slots) {
if (!ms->dirty_bitmap)
return -EINVAL;
ram_pages += ms->npages;
}
/* mark all the pages as dirty */
gmap_set_cmma_all_dirty(kvm->arch.gmap);
atomic64_set(&kvm->arch.cmma_dirty_pages, ram_pages);
kvm->arch.migration_mode = 1;
/*
* Set the flag and let KVM handle ESSA manually, potentially setting
* the cmma_d bit in some PGSTEs and increasing cmma_dirty_pages.
* At this point cmma_dirty_pages is still 0, and all existing PGSTEs
* have their cmma_d bit set to 0.
* Any newly allocated page table has its entries marked as cmma-clean,
* which is fine because the CMMA values are not dirty.
*/
WRITE_ONCE(kvm->arch.migration_mode, 1);
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_START_MIGRATION);
/*
* Mark all PGSTEs as cmma-dirty, increasing cmma_dirty_pages as needed,
* but without double-counting pages that have become dirty on their own
* in the meantime.
* At this point some pages might have become dirty on their own already
* and cmma_dirty_pages might therefore be non-zero.
*/
gmap_set_cmma_all_dirty(kvm->arch.gmap);
return 0;
}
/*
* Must be called with kvm->slots_lock to avoid races with ourselves and
* kvm_s390_vm_start_migration.
* Must be called with kvm->slots_lock to avoid races with ourselves,
* kvm_s390_vm_start_migration() and kvm_s390_get_cmma_bits().
*/
static int kvm_s390_vm_stop_migration(struct kvm *kvm)
{
/* migration mode already disabled */
if (!kvm->arch.migration_mode)
return 0;
kvm->arch.migration_mode = 0;
/*
* Unset the flag and propagate to all vCPUs. From now on the cmma_d
* bit will not be touched on any PGSTE.
* At this point cmma_dirty_pages is possibly non-zero, and thus some
* PGSTEs might have cmma_d set.
*/
WRITE_ONCE(kvm->arch.migration_mode, 0);
if (kvm->arch.use_cmma)
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION);
/* Clear cmma_d on all existing PGSTEs and set cmma_dirty_pages to 0. */
gmap_set_cmma_all_clean(kvm->arch.gmap);
atomic64_set(&kvm->arch.cmma_dirty_pages, 0);
/*
* At this point the system has the expected state: migration_mode is 0,
* cmma_dirty_pages is 0, and all existing PGSTEs have their cmma_d bit
* set to 0.
*/
return 0;
}
@@ -2317,8 +2345,8 @@ static int kvm_s390_get_cmma_bits(struct kvm *kvm,
static int kvm_s390_set_cmma_bits(struct kvm *kvm,
const struct kvm_s390_cmma_log *args)
{
struct kvm_s390_mmu_cache *mc;
u8 *bits = NULL;
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
u8 *bits __free(kvfree) = NULL;
int r = 0;
if (!kvm->arch.use_cmma)
@@ -2338,18 +2366,16 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
return -ENOMEM;
bits = vmalloc(array_size(sizeof(*bits), args->count));
if (!bits)
goto out;
return -ENOMEM;
r = copy_from_user(bits, (void __user *)args->values, args->count);
if (r) {
r = -EFAULT;
goto out;
}
if (r)
return -EFAULT;
do {
r = kvm_s390_mmu_cache_topup(mc);
if (r)
break;
return r;
scoped_guard(read_lock, &kvm->mmu_lock) {
r = dat_set_cmma_bits(mc, kvm->arch.gmap->asce, args->start_gfn,
args->count, args->mask, bits);
@@ -2357,9 +2383,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
} while (r == -ENOMEM);
set_bit(GMAP_FLAG_USES_CMM, &kvm->arch.gmap->flags);
out:
kvm_s390_free_mmu_cache(mc);
vfree(bits);
return r;
}
@@ -3584,7 +3608,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
vcpu->arch.gmap = vcpu->kvm->arch.gmap;
sca_add_vcpu(vcpu);
}
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0)
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0 ||
vcpu->kvm->arch.user_operexec)
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
}

View File

@@ -366,7 +366,9 @@ static int handle_sske(struct kvm_vcpu *vcpu)
if (rc > 1)
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
if (rc == -ENOMEM) {
kvm_s390_mmu_cache_topup(vcpu->arch.mc);
rc = kvm_s390_mmu_cache_topup(vcpu->arch.mc);
if (rc)
return rc;
continue;
}
if (rc < 0)
@@ -1122,7 +1124,9 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
if (rc > 1)
return kvm_s390_inject_program_int(vcpu, rc);
if (rc == -ENOMEM) {
kvm_s390_mmu_cache_topup(vcpu->arch.mc);
rc = kvm_s390_mmu_cache_topup(vcpu->arch.mc);
if (rc)
return rc;
continue;
}
if (rc < 0)
@@ -1232,7 +1236,7 @@ static int handle_essa(struct kvm_vcpu *vcpu)
: ESSA_SET_STABLE_IF_RESIDENT))
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
if (!vcpu->kvm->arch.migration_mode) {
if (!READ_ONCE(vcpu->kvm->arch.migration_mode)) {
/*
* CMMA is enabled in the KVM settings, but is disabled in
* the SIE block and in the mm_context, and we are not doing

View File

@@ -181,7 +181,8 @@ void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr)
if (IS_ERR_OR_NULL(ptep))
return;
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
if (pte_present(*ptep))
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
pte_unmap_unlock(ptep, ptl);
}
EXPORT_SYMBOL_GPL(gmap_helper_try_set_pte_unused);

View File

@@ -999,6 +999,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
if (ret == -EBUSY) {
amdxdna_umap_put(mapp);
mmput(mm);
goto again;
}
@@ -1009,11 +1010,13 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
if (mmu_interval_read_retry(&mapp->notifier, mapp->range.notifier_seq)) {
up_write(&xdna->notifier_lock);
amdxdna_umap_put(mapp);
mmput(mm);
goto again;
}
mapp->invalid = false;
up_write(&xdna->notifier_lock);
amdxdna_umap_put(mapp);
mmput(mm);
goto again;
put_mm:

View File

@@ -276,7 +276,7 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
if (ipc_buf)
memcpy(ipc_buf, rx_msg->ipc_hdr, sizeof(*ipc_buf));
if (rx_msg->jsm_msg) {
u32 size = min_t(int, rx_msg->ipc_hdr->data_size, sizeof(*jsm_msg));
u32 size = min(rx_msg->ipc_hdr->data_size, sizeof(*jsm_msg));
if (rx_msg->jsm_msg->result != VPU_JSM_STATUS_SUCCESS) {
ivpu_err(vdev, "IPC resp result error: %d\n", rx_msg->jsm_msg->result);

View File

@@ -977,7 +977,7 @@ static struct clk_rcg2 disp0_cc_mdss_mdp_clk_src = {
.name = "disp0_cc_mdss_mdp_clk_src",
.parent_data = disp0_cc_parent_data_5,
.num_parents = ARRAY_SIZE(disp0_cc_parent_data_5),
.ops = &clk_rcg2_shared_ops,
.ops = &clk_rcg2_shared_no_init_park_ops,
},
};
@@ -991,7 +991,7 @@ static struct clk_rcg2 disp1_cc_mdss_mdp_clk_src = {
.name = "disp1_cc_mdss_mdp_clk_src",
.parent_data = disp1_cc_parent_data_5,
.num_parents = ARRAY_SIZE(disp1_cc_parent_data_5),
.ops = &clk_rcg2_shared_ops,
.ops = &clk_rcg2_shared_no_init_park_ops,
},
};

View File

@@ -580,7 +580,7 @@ static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
.parent_data = disp_cc_parent_data_6,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_6),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
.ops = &clk_rcg2_shared_no_init_park_ops,
},
};

View File

@@ -3921,7 +3921,7 @@ static const unsigned long peric0_clk_regs[] __initconst = {
CLK_CON_DIV_DIV_CLK_PERIC0_USI4_USI,
CLK_CON_DIV_DIV_CLK_PERIC0_USI5_USI,
CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI,
CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI,
CLK_CON_DIV_DIV_CLK_PERIC0_USI7_USI,
CLK_CON_DIV_DIV_CLK_PERIC0_USI8_USI,
CLK_CON_BUF_CLKBUF_PERIC0_IP,
CLK_CON_GAT_CLK_BLK_PERIC0_UID_PERIC0_CMU_PERIC0_IPCLKPORT_PCLK,

View File

@@ -723,15 +723,9 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
return -ENOMEM;
priv->client.dev = dev;
priv->client.receive_cb = NULL;
priv->client.priv = priv;
priv->status.current_image = 0;
priv->status.fail_image = 0;
priv->status.error_location = 0;
priv->status.error_details = 0;
priv->status.version = 0;
priv->status.state = 0;
priv->retry_counter = INVALID_RETRY_COUNTER;
priv->max_retry = INVALID_RETRY_COUNTER;
priv->dcmf_version.dcmf0 = INVALID_DCMF_VERSION;
priv->dcmf_version.dcmf1 = INVALID_DCMF_VERSION;
priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION;
@@ -740,11 +734,11 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS;
priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS;
priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS;
priv->max_retry = INVALID_RETRY_COUNTER;
priv->spt0_address = INVALID_SPT_ADDRESS;
priv->spt1_address = INVALID_SPT_ADDRESS;
/* spt0/1_address and status fields default to 0 from kzalloc */
mutex_init(&priv->lock);
init_completion(&priv->completion);
priv->chan = stratix10_svc_request_channel_byname(&priv->client,
SVC_CLIENT_RSU);
if (IS_ERR(priv->chan)) {
@@ -756,11 +750,9 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
ret = stratix10_svc_add_async_client(priv->chan, false);
if (ret) {
dev_err(dev, "failed to add async client\n");
stratix10_svc_free_channel(priv->chan);
return ret;
goto free_channel;
}
init_completion(&priv->completion);
platform_set_drvdata(pdev, priv);
/* get the initial state from firmware */
@@ -768,41 +760,44 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
rsu_async_status_callback);
if (ret) {
dev_err(dev, "Error, getting RSU status %i\n", ret);
stratix10_svc_remove_async_client(priv->chan);
stratix10_svc_free_channel(priv->chan);
return ret;
goto remove_async_client;
}
/* get DCMF version from firmware */
ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION,
0, rsu_dcmf_version_callback);
ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION, 0,
rsu_dcmf_version_callback);
if (ret) {
dev_err(dev, "Error, getting DCMF version %i\n", ret);
stratix10_svc_free_channel(priv->chan);
goto remove_async_client;
}
ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS,
0, rsu_dcmf_status_callback);
ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS, 0,
rsu_dcmf_status_callback);
if (ret) {
dev_err(dev, "Error, getting DCMF status %i\n", ret);
stratix10_svc_free_channel(priv->chan);
goto remove_async_client;
}
ret = rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0,
rsu_max_retry_callback);
if (ret) {
dev_err(dev, "Error, getting RSU max retry %i\n", ret);
stratix10_svc_free_channel(priv->chan);
goto remove_async_client;
}
ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_GET_SPT_TABLE, 0,
rsu_async_get_spt_table_callback);
if (ret) {
dev_err(dev, "Error, getting SPT table %i\n", ret);
stratix10_svc_free_channel(priv->chan);
goto remove_async_client;
}
return 0;
remove_async_client:
stratix10_svc_remove_async_client(priv->chan);
free_channel:
stratix10_svc_free_channel(priv->chan);
return ret;
}

View File

@@ -212,6 +212,7 @@ struct stratix10_async_chan {
/**
* struct stratix10_async_ctrl - Control structure for Stratix10
* asynchronous operations
* @supported: Flag indicating whether the system supports async operations
* @initialized: Flag indicating whether the control structure has
* been initialized
* @invoke_fn: Function pointer for invoking Stratix10 service calls
@@ -228,6 +229,7 @@ struct stratix10_async_chan {
*/
struct stratix10_async_ctrl {
bool supported;
bool initialized;
void (*invoke_fn)(struct stratix10_async_ctrl *actrl,
const struct arm_smccc_1_2_regs *args,
@@ -1103,6 +1105,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_request_channel_byname);
* Return: 0 on success, or a negative error code on failure:
* -EINVAL if the channel is NULL or the async controller is
* not initialized.
* -EOPNOTSUPP if async operations are not supported.
* -EALREADY if the async channel is already allocated.
* -ENOMEM if memory allocation fails.
* Other negative values if ID allocation fails.
@@ -1121,6 +1124,9 @@ int stratix10_svc_add_async_client(struct stratix10_svc_chan *chan,
ctrl = chan->ctrl;
actrl = &ctrl->actrl;
if (!actrl->supported)
return -EOPNOTSUPP;
if (!actrl->initialized) {
dev_err(ctrl->dev, "Async controller not initialized\n");
return -EINVAL;
@@ -1562,6 +1568,7 @@ static inline void stratix10_smc_1_2(struct stratix10_async_ctrl *actrl,
* initialized, -ENOMEM if memory allocation fails,
* -EADDRINUSE if the client ID is already reserved, or other
* negative error codes on failure.
* -EOPNOTSUPP if system doesn't support async operations.
*/
static int stratix10_svc_async_init(struct stratix10_svc_controller *controller)
{
@@ -1585,10 +1592,12 @@ static int stratix10_svc_async_init(struct stratix10_svc_controller *controller)
!(res.a1 > ASYNC_ATF_MINIMUM_MAJOR_VERSION ||
(res.a1 == ASYNC_ATF_MINIMUM_MAJOR_VERSION &&
res.a2 >= ASYNC_ATF_MINIMUM_MINOR_VERSION))) {
dev_err(dev,
"Intel Service Layer Driver: ATF version is not compatible for async operation\n");
return -EINVAL;
dev_info(dev,
"Intel Service Layer Driver: ATF version is not compatible for async operation\n");
actrl->supported = false;
return -EOPNOTSUPP;
}
actrl->supported = true;
actrl->invoke_fn = stratix10_smc_1_2;
@@ -1952,10 +1961,14 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
init_completion(&controller->complete_status);
ret = stratix10_svc_async_init(controller);
if (ret) {
if (ret == -EOPNOTSUPP) {
dev_info(dev, "Intel Service Layer Driver Initialized (sync-only mode)\n");
} else if (ret) {
dev_dbg(dev, "Intel Service Layer Driver: Error on stratix10_svc_async_init %d\n",
ret);
goto err_destroy_pool;
} else {
dev_info(dev, "Intel Service Layer Driver Initialized\n");
}
fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;

View File

@@ -17,6 +17,7 @@
#include <linux/irq.h>
#include <linux/irq_sim.h>
#include <linux/irqdomain.h>
#include <linux/limits.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -578,7 +579,7 @@ static int __init gpio_mockup_register_chip(int idx)
static int __init gpio_mockup_init(void)
{
int i, num_chips, err;
int i, num_chips, err, base, ngpio;
if ((gpio_mockup_num_ranges % 2) ||
(gpio_mockup_num_ranges > GPIO_MOCKUP_MAX_RANGES))
@@ -592,8 +593,19 @@ static int __init gpio_mockup_init(void)
* always be greater than 0.
*/
for (i = 0; i < num_chips; i++) {
if (gpio_mockup_range_ngpio(i) < 0)
base = gpio_mockup_range_base(i);
ngpio = gpio_mockup_range_ngpio(i);
if (ngpio <= 0)
return -EINVAL;
if (base < 0) {
if (ngpio > U16_MAX)
return -EINVAL;
} else {
if (ngpio <= base || ngpio - base > U16_MAX)
return -EINVAL;
}
}
gpio_mockup_dbg_dir = debugfs_create_dir("gpio-mockup", NULL);

View File

@@ -996,7 +996,7 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
BUG();
}
if (IS_REACHABLE(CONFIG_PWM))
if (IS_REACHABLE(CONFIG_PWM) && mvchip->mvpwm)
mvebu_pwm_suspend(mvchip);
return 0;
@@ -1048,7 +1048,7 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
BUG();
}
if (IS_REACHABLE(CONFIG_PWM))
if (IS_REACHABLE(CONFIG_PWM) && mvchip->mvpwm)
mvebu_pwm_resume(mvchip);
return 0;

View File

@@ -802,8 +802,10 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
irq_set_chained_handler_and_data(bank->irq, NULL, NULL);
if (bank->domain)
if (bank->domain) {
irq_domain_remove_generic_chips(bank->domain);
irq_domain_remove(bank->domain);
}
gpiochip_remove(&bank->gpio_chip);
}

View File

@@ -1014,6 +1014,7 @@ static void zynq_gpio_remove(struct platform_device *pdev)
gpiochip_remove(&gpio->chip);
device_set_wakeup_capable(&pdev->dev, 0);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
}
static struct platform_driver zynq_gpio_driver = {

View File

@@ -1066,11 +1066,6 @@ int of_gpiochip_add(struct gpio_chip *chip)
of_node_get(np);
for_each_available_child_of_node_scoped(np, child) {
if (of_property_read_bool(child, "gpio-hog"))
of_node_set_flag(child, OF_POPULATED);
}
return ret;
}

View File

@@ -1031,9 +1031,17 @@ static int gpiochip_hog_lines(struct gpio_chip *gc)
if (!fwnode_property_present(fwnode, "gpio-hog"))
continue;
/* The hog may have been handled by another gpio_chip on the same fwnode */
if (is_of_node(fwnode) &&
of_node_check_flag(to_of_node(fwnode), OF_POPULATED))
continue;
ret = gpiochip_add_hog(gc, fwnode);
if (ret)
return ret;
if (is_of_node(fwnode))
of_node_set_flag(to_of_node(fwnode), OF_POPULATED);
}
return 0;
@@ -1291,7 +1299,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
ret = gpiochip_hog_lines(gc);
if (ret)
goto err_remove_of_chip;
goto err_free_hogs;
ret = gpiochip_irqchip_init_valid_mask(gc);
if (ret)

View File

@@ -1277,6 +1277,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
{
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
struct amdgpu_job *leader = p->gang_leader;
struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_bo_list_entry *e;
struct drm_gem_object *gobj;
unsigned long index;
@@ -1322,7 +1323,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
amdgpu_hmm_range_free(e->range);
e->range = NULL;
}
if (r) {
if (r || !list_empty(&vm->invalidated)) {
r = -EAGAIN;
mutex_unlock(&p->adev->notifier_lock);
return r;

View File

@@ -593,7 +593,7 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
static int
amdgpu_userq_wait_count_fences(struct drm_file *filp,
struct drm_amdgpu_userq_wait *wait_info,
u32 *syncobj_handles, u32 *timeline_points,
u32 *syncobj_handles, u64 *timeline_points,
u32 *timeline_handles,
struct drm_gem_object **gobj_write,
struct drm_gem_object **gobj_read)
@@ -703,7 +703,7 @@ amdgpu_userq_wait_add_fence(struct drm_amdgpu_userq_wait *wait_info,
static int
amdgpu_userq_wait_return_fence_info(struct drm_file *filp,
struct drm_amdgpu_userq_wait *wait_info,
u32 *syncobj_handles, u32 *timeline_points,
u32 *syncobj_handles, u64 *timeline_points,
u32 *timeline_handles,
struct drm_gem_object **gobj_write,
struct drm_gem_object **gobj_read)
@@ -906,7 +906,8 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
int num_points, num_syncobj, num_read_bo_handles, num_write_bo_handles;
u32 *syncobj_handles, *timeline_points, *timeline_handles;
u32 *syncobj_handles, *timeline_handles;
u64 *timeline_points;
struct drm_amdgpu_userq_wait *wait_info = data;
struct drm_gem_object **gobj_write;
struct drm_gem_object **gobj_read;
@@ -935,7 +936,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
}
ptr = u64_to_user_ptr(wait_info->syncobj_timeline_points);
timeline_points = memdup_array_user(ptr, num_points, sizeof(u32));
timeline_points = memdup_array_user(ptr, num_points, sizeof(u64));
if (IS_ERR(timeline_points)) {
r = PTR_ERR(timeline_points);
goto free_timeline_handles;

View File

@@ -832,6 +832,12 @@ int kfd_dbg_trap_enable(struct kfd_process *target, uint32_t fd,
if (copy_to_user(runtime_info, (void *)&target->runtime_info, copy_size)) {
kfd_dbg_trap_deactivate(target, false, 0);
fput(target->dbg_ev_file);
target->dbg_ev_file = NULL;
if (target->debugger_process)
atomic_dec(&target->debugger_process->debugged_process_count);
target->debug_trap_enabled = false;
kfd_unref_process(target);
r = -EFAULT;
}

View File

@@ -795,6 +795,8 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events)
struct kfd_event_waiter *event_waiters;
uint32_t i;
if (num_events > KFD_SIGNAL_EVENT_LIMIT)
return NULL;
event_waiters = kzalloc_objs(struct kfd_event_waiter, num_events);
if (!event_waiters)
return NULL;

View File

@@ -254,8 +254,10 @@ void kfd_smi_event_update_vmfault(struct kfd_node *dev, uint16_t pasid)
if (task_info) {
/* Report VM faults from user applications, not retry from kernel */
if (task_info->task.pid)
kfd_smi_event_add(0, dev, KFD_SMI_EVENT_VMFAULT, KFD_EVENT_FMT_VMFAULT(
task_info->task.pid, task_info->task.comm));
kfd_smi_event_add(task_info->tgid, dev,
KFD_SMI_EVENT_VMFAULT,
KFD_EVENT_FMT_VMFAULT(task_info->task.pid,
task_info->task.comm));
amdgpu_vm_put_task_info(task_info);
}
}
@@ -356,7 +358,7 @@ void kfd_smi_event_process(struct kfd_process_device *pdd, bool start)
task_info = amdgpu_vm_get_task_info_vm(avm);
if (task_info) {
kfd_smi_event_add(0, pdd->dev,
kfd_smi_event_add(task_info->tgid, pdd->dev,
start ? KFD_SMI_EVENT_PROCESS_START :
KFD_SMI_EVENT_PROCESS_END,
KFD_EVENT_FMT_PROCESS(task_info->task.pid,

View File

@@ -10083,7 +10083,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
continue;
bundle->surface_updates[planes_count].surface = dc_plane;
if (new_pcrtc_state->color_mgmt_changed) {
if (new_pcrtc_state->color_mgmt_changed || new_plane_state->color_mgmt_changed) {
bundle->surface_updates[planes_count].gamma = &dc_plane->gamma_correction;
bundle->surface_updates[planes_count].in_transfer_func = &dc_plane->in_transfer_func;
bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix;
@@ -11824,6 +11824,10 @@ static bool should_reset_plane(struct drm_atomic_state *state,
if (new_crtc_state->color_mgmt_changed)
return true;
/* Plane color pipeline or its colorop changes. */
if (new_plane_state->color_mgmt_changed)
return true;
/*
* On zpos change, planes need to be reordered by removing and re-adding
* them one by one to the dc state, in order of descending zpos.
@@ -13446,17 +13450,15 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
}
/* Handle MCCS */
if (do_mccs)
if (do_mccs) {
dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
if ((sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
as_type == FREESYNC_TYPE_PCON_IN_WHITELIST) &&
(!sink->edid_caps.freesync_vcp_code ||
(sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)))
freesync_capable = false;
if (sink->edid_caps.freesync_vcp_code && !sink->mccs_caps.freesync_supported)
freesync_capable = false;
if (do_mccs && sink->mccs_caps.freesync_supported && freesync_capable)
dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
if (sink->mccs_caps.freesync_supported && freesync_capable)
dm_helpers_mccs_vcp_set(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink);
}
update:
if (dm_con_state)

View File

@@ -830,7 +830,7 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
case DRM_COLOROP_1D_LUT:
drm_printf(p, "\tsize=%d\n", colorop->size);
drm_printf(p, "\tinterpolation=%s\n",
drm_get_colorop_lut1d_interpolation_name(colorop->lut1d_interpolation));
drm_get_colorop_lut1d_interpolation_name(state->lut1d_interpolation));
drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
break;
case DRM_COLOROP_CTM_3X4:
@@ -842,7 +842,7 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
case DRM_COLOROP_3D_LUT:
drm_printf(p, "\tsize=%d\n", colorop->size);
drm_printf(p, "\tinterpolation=%s\n",
drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
drm_get_colorop_lut3d_interpolation_name(state->lut3d_interpolation));
drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
break;
default:

View File

@@ -265,13 +265,19 @@ EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
*
* Helper function to select the color pipeline on a plane by setting
* it to the first drm_colorop element of the pipeline.
*
* Return: true if plane color pipeline value changed, false otherwise.
*/
void
bool
drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
struct drm_colorop *colorop)
{
struct drm_plane *plane = plane_state->plane;
/* Color pipeline didn't change */
if (plane_state->color_pipeline == colorop)
return false;
if (colorop)
drm_dbg_atomic(plane->dev,
"Set [COLOROP:%d] for [PLANE:%d:%s] state %p\n",
@@ -283,6 +289,8 @@ drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
plane->base.id, plane->name, plane_state);
plane_state->color_pipeline = colorop;
return true;
}
EXPORT_SYMBOL(drm_atomic_set_colorop_for_plane);
@@ -604,7 +612,7 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
if (val && !colorop)
return -EACCES;
drm_atomic_set_colorop_for_plane(state, colorop);
state->color_mgmt_changed |= drm_atomic_set_colorop_for_plane(state, colorop);
} else if (property == config->prop_fb_damage_clips) {
ret = drm_property_replace_blob_from_id(dev,
&state->fb_damage_clips,
@@ -713,11 +721,11 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
struct drm_colorop_state *state,
struct drm_property *property,
uint64_t val)
uint64_t val,
bool *replaced)
{
ssize_t elem_size = -1;
ssize_t size = -1;
bool replaced = false;
switch (colorop->type) {
case DRM_COLOROP_1D_LUT:
@@ -739,28 +747,45 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
&state->data,
val,
-1, size, elem_size,
&replaced);
replaced);
}
static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
struct drm_colorop_state *state,
struct drm_file *file_priv,
struct drm_property *property,
uint64_t val)
uint64_t val,
bool *replaced)
{
if (property == colorop->bypass_property) {
state->bypass = val;
if (state->bypass != val) {
state->bypass = val;
*replaced = true;
}
} else if (property == colorop->lut1d_interpolation_property) {
colorop->lut1d_interpolation = val;
if (state->lut1d_interpolation != val) {
state->lut1d_interpolation = val;
*replaced = true;
}
} else if (property == colorop->curve_1d_type_property) {
state->curve_1d_type = val;
if (state->curve_1d_type != val) {
state->curve_1d_type = val;
*replaced = true;
}
} else if (property == colorop->multiplier_property) {
state->multiplier = val;
if (state->multiplier != val) {
state->multiplier = val;
*replaced = true;
}
} else if (property == colorop->lut3d_interpolation_property) {
colorop->lut3d_interpolation = val;
if (state->lut3d_interpolation != val) {
state->lut3d_interpolation = val;
*replaced = true;
}
} else if (property == colorop->data_property) {
return drm_atomic_color_set_data_property(colorop, state,
property, val);
property, val,
replaced);
} else {
drm_dbg_atomic(colorop->dev,
"[COLOROP:%d:%d] unknown property [PROP:%d:%s]\n",
@@ -782,7 +807,7 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
else if (property == colorop->bypass_property)
*val = state->bypass;
else if (property == colorop->lut1d_interpolation_property)
*val = colorop->lut1d_interpolation;
*val = state->lut1d_interpolation;
else if (property == colorop->curve_1d_type_property)
*val = state->curve_1d_type;
else if (property == colorop->multiplier_property)
@@ -790,7 +815,7 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
else if (property == colorop->size_property)
*val = colorop->size;
else if (property == colorop->lut3d_interpolation_property)
*val = colorop->lut3d_interpolation;
*val = state->lut3d_interpolation;
else if (property == colorop->data_property)
*val = (state->data) ? state->data->base.id : 0;
else
@@ -1275,8 +1300,10 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
break;
}
case DRM_MODE_OBJECT_COLOROP: {
struct drm_plane_state *plane_state;
struct drm_colorop *colorop = obj_to_colorop(obj);
struct drm_colorop_state *colorop_state;
bool replaced = false;
colorop_state = drm_atomic_get_colorop_state(state, colorop);
if (IS_ERR(colorop_state)) {
@@ -1285,7 +1312,18 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
}
ret = drm_atomic_colorop_set_property(colorop, colorop_state,
file_priv, prop, prop_value);
file_priv, prop, prop_value,
&replaced);
if (ret || !replaced)
break;
plane_state = drm_atomic_get_plane_state(state, colorop->plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
break;
}
plane_state->color_mgmt_changed |= replaced;
break;
}
default:

View File

@@ -342,7 +342,6 @@ int drm_plane_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_color
colorop->lut1d_interpolation_property = prop;
drm_object_attach_property(&colorop->base, prop, interpolation);
colorop->lut1d_interpolation = interpolation;
/* data */
ret = drm_colorop_create_data_prop(dev, colorop);
@@ -442,7 +441,6 @@ int drm_plane_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *col
colorop->lut3d_interpolation_property = prop;
drm_object_attach_property(&colorop->base, prop, interpolation);
colorop->lut3d_interpolation = interpolation;
/* data */
ret = drm_colorop_create_data_prop(dev, colorop);
@@ -521,6 +519,20 @@ static void __drm_colorop_state_reset(struct drm_colorop_state *colorop_state,
&val);
colorop_state->curve_1d_type = val;
}
if (colorop->lut1d_interpolation_property) {
if (!drm_object_property_get_default_value(&colorop->base,
colorop->lut1d_interpolation_property,
&val))
colorop_state->lut1d_interpolation = val;
}
if (colorop->lut3d_interpolation_property) {
if (!drm_object_property_get_default_value(&colorop->base,
colorop->lut3d_interpolation_property,
&val))
colorop_state->lut3d_interpolation = val;
}
}
/**

View File

@@ -4678,10 +4678,17 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp)
if (intel_dp->edp_dpcd[0] >= DP_EDP_14) {
__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
int ret;
int i;
drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
sink_rates, sizeof(sink_rates));
ret = drm_dp_dpcd_read_data(&intel_dp->aux,
DP_SUPPORTED_LINK_RATES,
sink_rates, sizeof(sink_rates));
if (ret < 0) {
drm_dbg_kms(display->drm,
"Unable to read eDP supported link rates, using default rates\n");
memset(sink_rates, 0, sizeof(sink_rates));
}
for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
int rate;

View File

@@ -18,6 +18,17 @@
#include "i915_gem_tiling.h"
#include "i915_scatterlist.h"
/* Abuse scatterlist to store pointer instead of struct page. */
static inline void __set_phys_vaddr(struct scatterlist *sg, void *vaddr)
{
sg_assign_page(sg, (struct page *)vaddr);
}
static inline void *__get_phys_vaddr(struct scatterlist *sg)
{
return (void *)sg_page(sg);
}
static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
{
struct address_space *mapping = obj->base.filp->f_mapping;
@@ -58,7 +69,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
sg->offset = 0;
sg->length = obj->base.size;
sg_assign_page(sg, (struct page *)vaddr);
__set_phys_vaddr(sg, vaddr);
sg_dma_address(sg) = dma;
sg_dma_len(sg) = obj->base.size;
@@ -99,7 +110,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
struct sg_table *pages)
{
dma_addr_t dma = sg_dma_address(pages->sgl);
void *vaddr = sg_page(pages->sgl);
void *vaddr = __get_phys_vaddr(pages->sgl);
__i915_gem_object_release_shmem(obj, pages, false);
@@ -139,7 +150,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
int i915_gem_object_pwrite_phys(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_pwrite *args)
{
void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
void *vaddr = __get_phys_vaddr(obj->mm.pages->sgl) + args->offset;
char __user *user_data = u64_to_user_ptr(args->data_ptr);
struct drm_i915_private *i915 = to_i915(obj->base.dev);
int err;
@@ -170,7 +181,7 @@ int i915_gem_object_pwrite_phys(struct drm_i915_gem_object *obj,
int i915_gem_object_pread_phys(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_pread *args)
{
void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
void *vaddr = __get_phys_vaddr(obj->mm.pages->sgl) + args->offset;
char __user *user_data = u64_to_user_ptr(args->data_ptr);
int err;

View File

@@ -290,15 +290,16 @@ static bool require_uniform_address_uniform(struct vc4_validated_shader_info *va
{
uint32_t o = validated_shader->num_uniform_addr_offsets;
uint32_t num_uniforms = validated_shader->uniforms_size / 4;
u32 *offsets;
validated_shader->uniform_addr_offsets =
krealloc(validated_shader->uniform_addr_offsets,
(o + 1) *
sizeof(*validated_shader->uniform_addr_offsets),
GFP_KERNEL);
if (!validated_shader->uniform_addr_offsets)
offsets = krealloc_array(validated_shader->uniform_addr_offsets,
o + 1,
sizeof(*validated_shader->uniform_addr_offsets),
GFP_KERNEL);
if (!offsets)
return false;
validated_shader->uniform_addr_offsets = offsets;
validated_shader->uniform_addr_offsets[o] = num_uniforms;
validated_shader->num_uniform_addr_offsets++;

View File

@@ -124,7 +124,10 @@ static void virtio_gpu_remove(struct virtio_device *vdev)
struct drm_device *dev = vdev->priv;
drm_dev_unplug(dev);
drm_atomic_helper_shutdown(dev);
if (drm_core_check_feature(dev, DRIVER_ATOMIC))
drm_atomic_helper_shutdown(dev);
virtio_gpu_deinit(dev);
drm_dev_put(dev);
}

View File

@@ -65,8 +65,10 @@ static int virtio_gpu_dma_fence_wait(struct virtio_gpu_submit *submit,
dma_fence_unwrap_for_each(f, &itr, fence) {
err = virtio_gpu_do_fence_wait(submit, f);
if (err)
if (err) {
dma_fence_put(itr.chain);
return err;
}
}
return 0;

View File

@@ -124,6 +124,15 @@ int xe_display_init_early(struct xe_device *xe)
intel_display_driver_early_probe(display);
intel_display_device_info_runtime_init(display);
/* Display may have been disabled at runtime init */
if (!intel_display_device_present(display)) {
xe->info.probe_display = false;
unset_display_features(xe);
return 0;
}
/* Early display init.. */
intel_opregion_setup(display);
@@ -137,8 +146,6 @@ int xe_display_init_early(struct xe_device *xe)
intel_bw_init_hw(display);
intel_display_device_info_runtime_init(display);
err = intel_display_driver_probe_noirq(display);
if (err)
goto err_opregion;

View File

@@ -52,7 +52,7 @@ static struct xe_drm_ras_counter *allocate_and_copy_counters(struct xe_device *x
struct xe_drm_ras_counter *counter;
int i;
counter = kcalloc(DRM_XE_RAS_ERR_COMP_MAX, sizeof(*counter), GFP_KERNEL);
counter = drmm_kcalloc(&xe->drm, DRM_XE_RAS_ERR_COMP_MAX, sizeof(*counter), GFP_KERNEL);
if (!counter)
return ERR_PTR(-ENOMEM);
@@ -100,54 +100,47 @@ static int assign_node_params(struct xe_device *xe, struct drm_ras_node *node,
return 0;
}
static void cleanup_node_param(struct xe_drm_ras *ras, const enum drm_xe_ras_error_severity severity)
static void cleanup_node_param(struct drm_ras_node *node)
{
struct drm_ras_node *node = &ras->node[severity];
kfree(ras->info[severity]);
ras->info[severity] = NULL;
kfree(node->device_name);
node->device_name = NULL;
}
static void cleanup_node(struct drm_device *drm, void *node)
{
drm_ras_node_unregister(node);
cleanup_node_param(node);
}
static int register_nodes(struct xe_device *xe)
{
struct xe_drm_ras *ras = &xe->ras;
int i;
struct drm_ras_node *node;
int i, ret;
for_each_error_severity(i) {
struct drm_ras_node *node = &ras->node[i];
int ret;
node = &ras->node[i];
ret = assign_node_params(xe, node, i);
if (ret) {
cleanup_node_param(ras, i);
return ret;
}
if (ret)
goto free_param;
ret = drm_ras_node_register(node);
if (ret) {
cleanup_node_param(ras, i);
return ret;
}
if (ret)
goto free_param;
ret = drmm_add_action_or_reset(&xe->drm, cleanup_node, node);
if (ret)
goto null_info;
}
return 0;
}
static void xe_drm_ras_unregister_nodes(struct drm_device *device, void *arg)
{
struct xe_device *xe = arg;
struct xe_drm_ras *ras = &xe->ras;
int i;
for_each_error_severity(i) {
struct drm_ras_node *node = &ras->node[i];
drm_ras_node_unregister(node);
cleanup_node_param(ras, i);
}
free_param:
cleanup_node_param(node);
null_info:
ras->info[i] = NULL;
return ret;
}
/**
@@ -176,11 +169,5 @@ int xe_drm_ras_init(struct xe_device *xe)
return err;
}
err = drmm_add_action_or_reset(&xe->drm, xe_drm_ras_unregister_nodes, xe);
if (err) {
drm_err(&xe->drm, "Failed to add action for Xe DRM RAS (%pe)\n", ERR_PTR(err));
return err;
}
return 0;
}

View File

@@ -157,6 +157,11 @@ static void set_exec_queue_banned(struct xe_exec_queue *q)
atomic_or(EXEC_QUEUE_STATE_BANNED, &q->guc->state);
}
static void clear_exec_queue_banned(struct xe_exec_queue *q)
{
atomic_andnot(EXEC_QUEUE_STATE_BANNED, &q->guc->state);
}
static bool exec_queue_suspended(struct xe_exec_queue *q)
{
return atomic_read(&q->guc->state) & EXEC_QUEUE_STATE_SUSPENDED;
@@ -1361,7 +1366,8 @@ static bool check_timeout(struct xe_exec_queue *q, struct xe_sched_job *job)
xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job),
q->guc->id);
return xe_sched_invalidate_job(job, 2);
/* GuC never scheduled this job - let the caller trigger a GT reset. */
return true;
}
ctx_timestamp = lower_32_bits(xe_lrc_timestamp(q->lrc[0]));
@@ -1458,6 +1464,21 @@ static void disable_scheduling(struct xe_exec_queue *q, bool immediate)
G2H_LEN_DW_SCHED_CONTEXT_MODE_SET, 1);
}
/*
* Recover via GT reset for a kernel queue, or for a GuC scheduling failure (job
* never started) on a queue that was not already killed or banned. An already
* banned queue must stay banned, so its unstarted jobs do not clear the ban or
* trigger a reset.
*/
static bool timeout_needs_gt_reset(struct xe_exec_queue *q, struct xe_sched_job *job,
bool skip_timeout_check)
{
if (q->flags & EXEC_QUEUE_FLAG_KERNEL)
return true;
return !skip_timeout_check && !xe_sched_job_started(job);
}
static enum drm_gpu_sched_stat
guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
{
@@ -1606,19 +1627,19 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job),
q->guc->id, q->flags);
/*
* Kernel jobs should never fail, nor should VM jobs if they do
* somethings has gone wrong and the GT needs a reset
*/
xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_KERNEL,
"Kernel-submitted job timed out\n");
xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q),
"VM job timed out on non-killed execqueue\n");
if (!wedged && (q->flags & EXEC_QUEUE_FLAG_KERNEL ||
(q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q)))) {
if (!xe_sched_invalidate_job(job, 2)) {
xe_gt_reset_async(q->gt);
goto rearm;
if (!wedged) {
if (timeout_needs_gt_reset(q, job, skip_timeout_check)) {
if (!xe_sched_invalidate_job(job, 2)) {
clear_exec_queue_banned(q);
xe_gt_reset_async(q->gt);
goto rearm;
}
if (q->flags & EXEC_QUEUE_FLAG_KERNEL) {
xe_gt_WARN(q->gt, true, "Kernel-submitted job timed out\n");
xe_device_declare_wedged(gt_to_xe(q->gt));
}
} else if (q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q)) {
xe_gt_WARN(q->gt, true, "VM job timed out on non-killed execqueue\n");
}
}

View File

@@ -255,9 +255,8 @@ static int send_tlb_inval_ctx_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
#undef EXEC_QUEUE_COUNT_FULL_THRESHOLD
/*
* Move exec queues to a temporary list to issue invalidations. The exec
* queue must active and a reference must be taken to prevent concurrent
* deregistrations.
* Move exec queues to a temporary list to issue invalidations. A
* reference must be taken to prevent concurrent deregistrations.
*
* List modification is safe because we hold 'vm->exec_queues.lock' for
* reading, which prevents external modifications. Using a per-GT list
@@ -266,7 +265,7 @@ static int send_tlb_inval_ctx_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
*/
list_for_each_entry_safe(q, next, &vm->exec_queues.list[id],
vm_exec_queue_link) {
if (q->ops->active(q) && xe_exec_queue_get_unless_zero(q)) {
if (xe_exec_queue_get_unless_zero(q)) {
last_q = q;
list_move_tail(&q->vm_exec_queue_link, &tlb_inval_list);
}

View File

@@ -219,9 +219,9 @@ static void log_hw_error(struct xe_tile *tile, const char *name,
struct xe_device *xe = tile_to_xe(tile);
if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE)
drm_warn(&xe->drm, "%s %s detected\n", name, severity_str);
drm_warn(&xe->drm, HW_ERR "%s %s detected\n", name, severity_str);
else
drm_err_ratelimited(&xe->drm, "%s %s detected\n", name, severity_str);
drm_err_ratelimited(&xe->drm, HW_ERR "%s %s detected\n", name, severity_str);
}
static void log_gt_err(struct xe_tile *tile, const char *name, int i, u32 err,
@@ -231,10 +231,10 @@ static void log_gt_err(struct xe_tile *tile, const char *name, int i, u32 err,
struct xe_device *xe = tile_to_xe(tile);
if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE)
drm_warn(&xe->drm, "%s %s detected, ERROR_STAT_GT_VECTOR%d:0x%08x\n",
drm_warn(&xe->drm, HW_ERR "%s %s detected, ERROR_STAT_GT_VECTOR%d:0x%08x\n",
name, severity_str, i, err);
else
drm_err_ratelimited(&xe->drm, "%s %s detected, ERROR_STAT_GT_VECTOR%d:0x%08x\n",
drm_err_ratelimited(&xe->drm, HW_ERR "%s %s detected, ERROR_STAT_GT_VECTOR%d:0x%08x\n",
name, severity_str, i, err);
}
@@ -251,9 +251,9 @@ static void log_soc_error(struct xe_tile *tile, const char * const *reg_info,
if (strcmp(name, "Undefined")) {
if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE)
drm_warn(&xe->drm, "%s SOC %s detected", name, severity_str);
drm_warn(&xe->drm, HW_ERR "%s SOC %s detected", name, severity_str);
else
drm_err_ratelimited(&xe->drm, "%s SOC %s detected", name, severity_str);
drm_err_ratelimited(&xe->drm, HW_ERR "%s SOC %s detected", name, severity_str);
atomic_inc(&info[index].counter);
}
}

View File

@@ -77,6 +77,8 @@ int xe_range_fence_insert(struct xe_range_fence_tree *tree,
} else if (err == 0) {
xe_range_fence_tree_insert(rfence, &tree->root);
return 0;
} else {
dma_fence_put(fence);
}
free:

View File

@@ -1383,55 +1383,66 @@ static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx,
return 0;
}
static void dma_exit(struct device *dev, struct lpi2c_imx_dma *dma)
{
if (dma->chan_rx)
dma_release_channel(dma->chan_rx);
if (dma->chan_tx)
dma_release_channel(dma->chan_tx);
devm_kfree(dev, dma);
}
static int lpi2c_dma_init(struct device *dev, dma_addr_t phy_addr)
{
struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
struct lpi2c_imx_dma *dma;
void *group;
int ret;
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
/*
* Open a devres group so that all resources allocated within
* this function can be released together if DMA init fails but
* probe continues in PIO mode.
*/
group = devres_open_group(dev, NULL, GFP_KERNEL);
if (!group)
return -ENOMEM;
dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
if (!dma) {
ret = -ENOMEM;
goto release_group;
}
dma->phy_addr = phy_addr;
/* Prepare for TX DMA: */
dma->chan_tx = dma_request_chan(dev, "tx");
dma->chan_tx = devm_dma_request_chan(dev, "tx");
if (IS_ERR(dma->chan_tx)) {
ret = PTR_ERR(dma->chan_tx);
if (ret != -ENODEV && ret != -EPROBE_DEFER)
dev_err(dev, "can't request DMA tx channel (%d)\n", ret);
dma->chan_tx = NULL;
goto dma_exit;
goto release_group;
}
/* Prepare for RX DMA: */
dma->chan_rx = dma_request_chan(dev, "rx");
dma->chan_rx = devm_dma_request_chan(dev, "rx");
if (IS_ERR(dma->chan_rx)) {
ret = PTR_ERR(dma->chan_rx);
if (ret != -ENODEV && ret != -EPROBE_DEFER)
dev_err(dev, "can't request DMA rx channel (%d)\n", ret);
dma->chan_rx = NULL;
goto dma_exit;
goto release_group;
}
/*
* DMA init succeeded. Remove the group marker but keep all resources
* bound to the device, they will be freed at device removal.
*/
devres_remove_group(dev, group);
lpi2c_imx->can_use_dma = true;
lpi2c_imx->dma = dma;
return 0;
dma_exit:
dma_exit(dev, dma);
release_group:
/*
* DMA init failed. Release ALL resources allocated inside this
* group (dma memory, TX channel if already acquired, etc.) so
* that a successful PIO-mode probe does not hold unused resources
* for the entire device lifetime.
*/
devres_release_group(dev, group);
return ret;
}

View File

@@ -1892,9 +1892,15 @@ static void i2c_imx_remove(struct platform_device *pdev)
static int i2c_imx_runtime_suspend(struct device *dev)
{
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
int ret;
ret = pinctrl_pm_select_sleep_state(dev);
if (ret)
return ret;
clk_disable(i2c_imx->clk);
return pinctrl_pm_select_sleep_state(dev);
return 0;
}
static int i2c_imx_runtime_resume(struct device *dev)
@@ -1907,10 +1913,13 @@ static int i2c_imx_runtime_resume(struct device *dev)
return ret;
ret = clk_enable(i2c_imx->clk);
if (ret)
if (ret) {
dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
pinctrl_pm_select_sleep_state(dev);
return ret;
}
return ret;
return 0;
}
static int i2c_imx_suspend(struct device *dev)

View File

@@ -660,8 +660,8 @@ static void cci_remove(struct platform_device *pdev)
if (cci->master[i].cci) {
i2c_del_adapter(&cci->master[i].adap);
of_node_put(cci->master[i].adap.dev.of_node);
cci_halt(cci, i);
}
cci_halt(cci, i);
}
disable_irq(cci->irq);

View File

@@ -725,8 +725,10 @@ static int riic_i2c_resume_noirq(struct device *dev)
return ret;
ret = pm_runtime_force_resume(dev);
if (ret)
if (ret) {
reset_control_assert(riic->rstc);
return ret;
}
ret = riic_init_hw(riic);
if (ret) {

View File

@@ -694,6 +694,9 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
if (!of_property_read_bool(i2c_dev->dev->of_node, "i2c-digital-filter"))
i2c_dev->dnf_dt = STM32F7_I2C_DNF_DEFAULT;
i2c_dev->analog_filter = of_property_read_bool(i2c_dev->dev->of_node,
"i2c-analog-filter");
do {
ret = stm32f7_i2c_compute_timing(i2c_dev, setup,
&i2c_dev->timing);
@@ -715,9 +718,6 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
return ret;
}
i2c_dev->analog_filter = of_property_read_bool(i2c_dev->dev->of_node,
"i2c-analog-filter");
dev_dbg(i2c_dev->dev, "I2C Speed(%i), Clk Source(%i)\n",
setup->speed_freq, setup->clock_src);
dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n",

View File

@@ -2115,9 +2115,9 @@ static const struct tegra_i2c_hw_feature tegra264_i2c_hw = {
static const struct tegra_i2c_hw_feature tegra410_i2c_hw = {
.has_continue_xfer_support = true,
.has_per_pkt_xfer_complete_irq = true,
.clk_divisor_hs_mode = 1,
.clk_divisor_hs_mode = 2,
.clk_divisor_std_mode = 0x3f,
.clk_divisor_fast_mode = 0x2c,
.clk_divisor_fast_mode = 0x2f,
.clk_divisor_fast_plus_mode = 0x11,
.has_config_load_reg = true,
.has_multi_master_mode = true,
@@ -2133,8 +2133,8 @@ static const struct tegra_i2c_hw_feature tegra410_i2c_hw = {
.thigh_fast_mode = 0x2,
.tlow_fastplus_mode = 0x2,
.thigh_fastplus_mode = 0x2,
.tlow_hs_mode = 0x8,
.thigh_hs_mode = 0x6,
.tlow_hs_mode = 0x5,
.thigh_hs_mode = 0x2,
.setup_hold_time_std_mode = 0x08080808,
.setup_hold_time_fast_mode = 0x02020202,
.setup_hold_time_fastplus_mode = 0x02020202,
@@ -2401,29 +2401,38 @@ static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
}
static int __maybe_unused tegra_i2c_suspend(struct device *dev)
{
/*
* Bring the controller up and hold a usage count so it stays
* available until the noirq phase.
*/
return pm_runtime_resume_and_get(dev);
}
static int __maybe_unused tegra_i2c_suspend_noirq(struct device *dev)
{
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
int err;
i2c_mark_adapter_suspended(&i2c_dev->adapter);
if (!pm_runtime_status_suspended(dev)) {
err = tegra_i2c_runtime_suspend(dev);
if (err)
return err;
}
return 0;
/*
* Runtime PM is already disabled at this point, so invoke the
* runtime_suspend callback directly to put the controller down.
*/
return tegra_i2c_runtime_suspend(dev);
}
static int __maybe_unused tegra_i2c_resume(struct device *dev)
static int __maybe_unused tegra_i2c_resume_noirq(struct device *dev)
{
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
int err;
/*
* We need to ensure that clocks are enabled so that registers can be
* restored in tegra_i2c_init().
* Runtime PM is still disabled at this point, so invoke the
* runtime_resume callback directly to bring the controller back up
* before re-initializing the hardware. The adapter is then marked
* resumed so that consumers can issue transfers from their own
* resume_noirq() handlers and onwards.
*/
err = tegra_i2c_runtime_resume(dev);
if (err)
@@ -2433,24 +2442,22 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
if (err)
return err;
/*
* In case we are runtime suspended, disable clocks again so that we
* don't unbalance the clock reference counts during the next runtime
* resume transition.
*/
if (pm_runtime_status_suspended(dev)) {
err = tegra_i2c_runtime_suspend(dev);
if (err)
return err;
}
i2c_mark_adapter_resumed(&i2c_dev->adapter);
return 0;
}
static int __maybe_unused tegra_i2c_resume(struct device *dev)
{
pm_runtime_put(dev);
return 0;
}
static const struct dev_pm_ops tegra_i2c_pm = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend_noirq,
tegra_i2c_resume_noirq)
SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume,
NULL)
};

View File

@@ -1918,12 +1918,18 @@ static int iommu_dma_iova_link_swiotlb(struct device *dev,
return 0;
}
/*
* After removing the partial head and tail, there may be no aligned
* middle left to map. The tail still gets bounced below.
*/
size -= iova_end_pad;
error = __dma_iova_link(dev, addr + mapped, phys + mapped, size, dir,
attrs);
if (error)
goto out_unmap;
mapped += size;
if (size) {
error = __dma_iova_link(dev, addr + mapped, phys + mapped,
size, dir, attrs);
if (error)
goto out_unmap;
mapped += size;
}
if (iova_end_pad) {
error = iommu_dma_iova_bounce_and_link(dev, addr + mapped,
@@ -1936,7 +1942,8 @@ static int iommu_dma_iova_link_swiotlb(struct device *dev,
return 0;
out_unmap:
dma_iova_unlink(dev, state, 0, mapped, dir, attrs);
if (mapped)
dma_iova_unlink(dev, state, offset, mapped, dir, attrs);
return error;
}

View File

@@ -310,6 +310,8 @@ struct fastrpc_user {
spinlock_t lock;
/* lock for allocations */
struct mutex mutex;
/* Reference count */
struct kref refcount;
};
/* Extract SMMU PA from consolidated IOVA */
@@ -386,7 +388,7 @@ static int fastrpc_map_get(struct fastrpc_map *map)
static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
struct fastrpc_map **ppmap)
struct fastrpc_map **ppmap, bool take_ref)
{
struct fastrpc_map *map = NULL;
struct dma_buf *buf;
@@ -401,6 +403,12 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
if (map->fd != fd || map->buf != buf)
continue;
if (take_ref) {
ret = fastrpc_map_get(map);
if (ret)
break;
}
*ppmap = map;
ret = 0;
break;
@@ -497,15 +505,57 @@ static void fastrpc_channel_ctx_put(struct fastrpc_channel_ctx *cctx)
kref_put(&cctx->refcount, fastrpc_channel_ctx_free);
}
static void fastrpc_context_put(struct fastrpc_invoke_ctx *ctx);
static void fastrpc_user_free(struct kref *ref)
{
struct fastrpc_user *fl = container_of(ref, struct fastrpc_user, refcount);
struct fastrpc_invoke_ctx *ctx, *n;
struct fastrpc_map *map, *m;
struct fastrpc_buf *buf, *b;
if (fl->init_mem)
fastrpc_buf_free(fl->init_mem);
list_for_each_entry_safe(ctx, n, &fl->pending, node) {
list_del(&ctx->node);
fastrpc_context_put(ctx);
}
list_for_each_entry_safe(map, m, &fl->maps, node)
fastrpc_map_put(map);
list_for_each_entry_safe(buf, b, &fl->mmaps, node) {
list_del(&buf->node);
fastrpc_buf_free(buf);
}
fastrpc_channel_ctx_put(fl->cctx);
mutex_destroy(&fl->mutex);
kfree(fl);
}
static void fastrpc_user_get(struct fastrpc_user *fl)
{
kref_get(&fl->refcount);
}
static void fastrpc_user_put(struct fastrpc_user *fl)
{
kref_put(&fl->refcount, fastrpc_user_free);
}
static void fastrpc_context_free(struct kref *ref)
{
struct fastrpc_invoke_ctx *ctx;
struct fastrpc_channel_ctx *cctx;
struct fastrpc_user *fl;
unsigned long flags;
int i;
ctx = container_of(ref, struct fastrpc_invoke_ctx, refcount);
cctx = ctx->cctx;
fl = ctx->fl;
for (i = 0; i < ctx->nbufs; i++)
fastrpc_map_put(ctx->maps[i]);
@@ -521,6 +571,8 @@ static void fastrpc_context_free(struct kref *ref)
kfree(ctx->olaps);
kfree(ctx);
/* Release the reference taken in fastrpc_context_alloc() */
fastrpc_user_put(fl);
fastrpc_channel_ctx_put(cctx);
}
@@ -628,6 +680,8 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
/* Released in fastrpc_context_put() */
fastrpc_channel_ctx_get(cctx);
/* Take a reference to user, released in fastrpc_context_free() */
fastrpc_user_get(user);
ctx->sc = sc;
ctx->retval = -1;
@@ -658,6 +712,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
spin_lock(&user->lock);
list_del(&ctx->node);
spin_unlock(&user->lock);
fastrpc_user_put(user);
fastrpc_channel_ctx_put(cctx);
kfree(ctx->maps);
kfree(ctx->olaps);
@@ -871,19 +926,10 @@ static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
u64 len, u32 attr, struct fastrpc_map **ppmap)
{
struct fastrpc_session_ctx *sess = fl->sctx;
int err = 0;
if (!fastrpc_map_lookup(fl, fd, ppmap, true))
return 0;
if (!fastrpc_map_lookup(fl, fd, ppmap)) {
if (!fastrpc_map_get(*ppmap))
return 0;
dev_dbg(sess->dev, "%s: Failed to get map fd=%d\n",
__func__, fd);
}
err = fastrpc_map_attach(fl, fd, len, attr, ppmap);
return err;
return fastrpc_map_attach(fl, fd, len, attr, ppmap);
}
/*
@@ -1041,7 +1087,7 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx)
pages[i].addr = ctx->maps[i]->dma_addr;
mmap_read_lock(current->mm);
vma = find_vma(current->mm, ctx->args[i].ptr);
vma = vma_lookup(current->mm, ctx->args[i].ptr);
if (vma)
pages[i].addr += (ctx->args[i].ptr & PAGE_MASK) -
vma->vm_start;
@@ -1153,7 +1199,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {
if (!fdlist[i])
break;
if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap))
if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false))
fastrpc_map_put(mmap);
}
@@ -1579,9 +1625,6 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
{
struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data;
struct fastrpc_channel_ctx *cctx = fl->cctx;
struct fastrpc_invoke_ctx *ctx, *n;
struct fastrpc_map *map, *m;
struct fastrpc_buf *buf, *b;
unsigned long flags;
fastrpc_release_current_dsp_process(fl);
@@ -1590,28 +1633,10 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
list_del(&fl->user);
spin_unlock_irqrestore(&cctx->lock, flags);
if (fl->init_mem)
fastrpc_buf_free(fl->init_mem);
list_for_each_entry_safe(ctx, n, &fl->pending, node) {
list_del(&ctx->node);
fastrpc_context_put(ctx);
}
list_for_each_entry_safe(map, m, &fl->maps, node)
fastrpc_map_put(map);
list_for_each_entry_safe(buf, b, &fl->mmaps, node) {
list_del(&buf->node);
fastrpc_buf_free(buf);
}
fastrpc_session_free(cctx, fl->sctx);
fastrpc_channel_ctx_put(cctx);
mutex_destroy(&fl->mutex);
kfree(fl);
file->private_data = NULL;
/* Release the reference taken in fastrpc_device_open */
fastrpc_user_put(fl);
return 0;
}
@@ -1655,6 +1680,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
spin_lock_irqsave(&cctx->lock, flags);
list_add_tail(&fl->user, &cctx->users);
spin_unlock_irqrestore(&cctx->lock, flags);
kref_init(&fl->refcount);
return 0;
}
@@ -2431,7 +2457,6 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
kref_init(&data->refcount);
dev_set_drvdata(&rpdev->dev, data);
rdev->dma_mask = &data->dma_mask;
dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32));
INIT_LIST_HEAD(&data->users);
@@ -2440,6 +2465,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
idr_init(&data->ctx_idr);
data->domain_id = domain_id;
data->rpdev = rpdev;
dev_set_drvdata(&rpdev->dev, data);
err = of_platform_populate(rdev->of_node, NULL, NULL, rdev);
if (err)
@@ -2513,6 +2539,9 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
if (len < sizeof(*rsp))
return -EINVAL;
if (!cctx)
return -ENODEV;
ctxid = ((rsp->ctx & FASTRPC_CTXID_MASK) >> 4);
spin_lock_irqsave(&cctx->lock, flags);

View File

@@ -1153,6 +1153,9 @@ static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma)
rmem = of_reserved_mem_lookup(np);
of_node_put(np);
if (!rmem)
return -ENODEV;
dma_addr = rmem->base;
/* Compute the number of hw descriptors according to the
* reserved memory size and the payload buffer size

View File

@@ -1880,6 +1880,11 @@ int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp)
continue;
}
/* Ensure PHC payload (timestamp, error_flags) is read
* after req_id update is observed
*/
dma_rmb();
/* req_id was updated by the device which indicates that
* PHC timestamp and error_flags are updated too,
* checking errors before retrieving timestamp

View File

@@ -277,7 +277,7 @@ int bnge_hwrm_func_backing_store_qcaps(struct bnge_dev *bd)
struct hwrm_func_backing_store_qcaps_v2_output *resp;
struct hwrm_func_backing_store_qcaps_v2_input *req;
struct bnge_ctx_mem_info *ctx;
u16 type;
u16 type, next_type;
int rc;
if (bd->ctx)
@@ -294,8 +294,8 @@ int bnge_hwrm_func_backing_store_qcaps(struct bnge_dev *bd)
resp = bnge_hwrm_req_hold(bd, req);
for (type = 0; type < BNGE_CTX_V2_MAX; ) {
struct bnge_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
for (type = 0; type < BNGE_CTX_INV; type = next_type) {
struct bnge_ctx_mem_type *ctxm;
u8 init_val, init_off, i;
__le32 *p;
u32 flags;
@@ -304,8 +304,14 @@ int bnge_hwrm_func_backing_store_qcaps(struct bnge_dev *bd)
rc = bnge_hwrm_req_send(bd, req);
if (rc)
goto ctx_done;
next_type = le16_to_cpu(resp->next_valid_type);
if (type >= BNGE_CTX_V2_MAX)
continue;
ctxm = &ctx->ctx_arr[type];
flags = le32_to_cpu(resp->flags);
type = le16_to_cpu(resp->next_valid_type);
if (!(flags &
FUNC_BACKING_STORE_QCAPS_V2_RESP_FLAGS_TYPE_VALID))
continue;

View File

@@ -5748,7 +5748,7 @@ static void bnxt_disable_int_sync(struct bnxt *bp)
{
int i;
if (!bp->irq_tbl)
if (!bp->irq_tbl || !bp->bnapi)
return;
atomic_inc(&bp->intr_sem);

View File

@@ -3144,7 +3144,7 @@ static int emac_probe(struct platform_device *ofdev)
netif_carrier_off(ndev);
err = devm_register_netdev(&ofdev->dev, ndev);
err = register_netdev(ndev);
if (err) {
printk(KERN_ERR "%pOF: failed to register net device (%d)!\n",
np, err);
@@ -3197,6 +3197,13 @@ static void emac_remove(struct platform_device *ofdev)
DBG(dev, "remove" NL);
/* Unregister network device before tearing down hardware
* to prevent use-after-free during deferred cleanup. This ensures
* the network stack stops all operations before hardware resources
* are released.
*/
unregister_netdev(dev->ndev);
cancel_work_sync(&dev->reset_work);
if (emac_has_feature(dev, EMAC_FTR_HAS_TAH))

View File

@@ -2633,6 +2633,8 @@ static const struct dpll_pin_ops ice_dpll_pin_ufl_ops = {
.state_on_dpll_set = ice_dpll_ufl_pin_state_set,
.state_on_dpll_get = ice_dpll_sw_pin_state_get,
.direction_get = ice_dpll_pin_sw_direction_get,
.prio_get = ice_dpll_sw_input_prio_get,
.prio_set = ice_dpll_sw_input_prio_set,
.frequency_get = ice_dpll_sw_pin_frequency_get,
.frequency_set = ice_dpll_sw_pin_frequency_set,
.esync_set = ice_dpll_sw_esync_set,

View File

@@ -51,7 +51,7 @@ void idpf_ptp_get_features_access(const struct idpf_adapter *adapter)
/* Set the device clock time */
direct = VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME;
mailbox = VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME;
mailbox = VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME_MB;
ptp->set_dev_clk_time_access = idpf_ptp_get_access(adapter,
direct,
mailbox);

View File

@@ -2780,7 +2780,7 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
goto put_err;
}
ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
ppdev->dev.of_node = pnp;
ppdev->dev.of_node = of_node_get(pnp);
ret = platform_device_add_resources(ppdev, &res, 1);
if (ret)

View File

@@ -3917,10 +3917,10 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
struct mvpp2_bm_pool *bm_pool;
struct page_pool *pp = NULL;
struct sk_buff *skb;
unsigned int frag_size;
unsigned int frag_size, rx_sync_size;
dma_addr_t dma_addr;
phys_addr_t phys_addr;
int pool, rx_bytes, err, ret;
int pool, rx_bytes, rx_offset, err, ret;
struct page *page;
void *data;
@@ -3933,6 +3933,8 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
rx_status = mvpp2_rxdesc_status_get(port, rx_desc);
rx_bytes = mvpp2_rxdesc_size_get(port, rx_desc);
rx_bytes -= MVPP2_MH_SIZE;
rx_sync_size = rx_bytes + MVPP2_MH_SIZE;
rx_offset = MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM;
dma_addr = mvpp2_rxdesc_dma_addr_get(port, rx_desc);
pool = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >>
@@ -3946,9 +3948,10 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
dma_dir = DMA_FROM_DEVICE;
}
dma_sync_single_for_cpu(dev->dev.parent, dma_addr,
rx_bytes + MVPP2_MH_SIZE,
dma_dir);
dma_sync_single_range_for_cpu(dev->dev.parent, dma_addr,
MVPP2_SKB_HEADROOM,
rx_sync_size,
dma_dir);
/* Buffer header not supported */
if (rx_status & MVPP2_RXD_BUF_HDR)
@@ -3970,6 +3973,12 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
else
frag_size = bm_pool->frag_size;
err = mvpp2_rx_refill(port, bm_pool, pp, pool);
if (err) {
netdev_err(port->dev, "failed to refill BM pools\n");
goto err_drop_frame;
}
if (xdp_prog) {
struct xdp_rxq_info *xdp_rxq;
@@ -3978,7 +3987,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
else
xdp_rxq = &rxq->xdp_rxq_long;
xdp_init_buff(&xdp, PAGE_SIZE, xdp_rxq);
xdp_init_buff(&xdp, bm_pool->frag_size, xdp_rxq);
xdp_prepare_buff(&xdp, data,
MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM,
rx_bytes, true);
@@ -3987,17 +3996,19 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
if (ret) {
xdp_ret |= ret;
err = mvpp2_rx_refill(port, bm_pool, pp, pool);
if (err) {
netdev_err(port->dev, "failed to refill BM pools\n");
goto err_drop_frame;
}
ps.rx_packets++;
ps.rx_bytes += rx_bytes;
continue;
}
rx_sync_size = max_t(unsigned int, rx_sync_size,
xdp.data_end - xdp.data_hard_start -
MVPP2_SKB_HEADROOM);
/* Update offset and length to reflect any XDP adjustments. */
rx_offset = xdp.data - data;
rx_bytes = xdp.data_end - xdp.data;
metasize = xdp.data - xdp.data_meta;
}
@@ -4007,8 +4018,20 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
skb = slab_build_skb(data);
if (!skb) {
netdev_warn(port->dev, "skb build failed\n");
goto err_drop_frame;
if (pp) {
page_pool_put_page(pp, virt_to_head_page(data),
rx_sync_size, true);
} else {
dma_unmap_single_attrs(dev->dev.parent, dma_addr,
bm_pool->buf_size,
DMA_FROM_DEVICE,
DMA_ATTR_SKIP_CPU_SYNC);
mvpp2_frag_free(bm_pool, pp, data);
}
goto err_drop_frame_retired;
}
if (pp)
skb_mark_for_recycle(skb);
/* If we have RX hardware timestamping enabled, grab the
* timestamp from the queue and convert.
@@ -4019,16 +4042,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
skb_hwtstamps(skb));
}
err = mvpp2_rx_refill(port, bm_pool, pp, pool);
if (err) {
netdev_err(port->dev, "failed to refill BM pools\n");
dev_kfree_skb_any(skb);
goto err_drop_frame;
}
if (pp)
skb_mark_for_recycle(skb);
else
if (!pp)
dma_unmap_single_attrs(dev->dev.parent, dma_addr,
bm_pool->buf_size, DMA_FROM_DEVICE,
DMA_ATTR_SKIP_CPU_SYNC);
@@ -4036,7 +4050,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
ps.rx_packets++;
ps.rx_bytes += rx_bytes;
skb_reserve(skb, MVPP2_MH_SIZE + MVPP2_SKB_HEADROOM);
skb_reserve(skb, rx_offset);
skb_put(skb, rx_bytes);
if (metasize)
skb_metadata_set(skb, metasize);
@@ -4047,13 +4061,14 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
continue;
err_drop_frame:
dev->stats.rx_errors++;
mvpp2_rx_error(port, rx_desc);
/* Return the buffer to the pool */
if (rx_status & MVPP2_RXD_BUF_HDR)
mvpp2_buff_hdr_pool_put(port, rx_desc, pool, rx_status);
else
mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
err_drop_frame_retired:
dev->stats.rx_errors++;
mvpp2_rx_error(port, rx_desc);
}
if (xdp_ret & MVPP2_XDP_REDIR)

View File

@@ -1571,53 +1571,49 @@ static u8 npc_map2cn20k_flag(u8 flag)
return 0xff;
}
static void npc_cn20k_translate_action_flags(struct npc_kpu_profile_action *act)
{
u8 ltype, val;
if (act->lid != NPC_LID_LC)
return;
ltype = act->ltype;
if (ltype != NPC_LT_LC_IP &&
ltype != NPC_LT_LC_IP6 &&
ltype != NPC_LT_LC_IP_OPT &&
ltype != NPC_LT_LC_IP6_EXT)
return;
switch (act->flags) {
case NPC_F_LC_U_IP_FRAG:
case NPC_F_LC_U_IP6_FRAG:
case NPC_F_LC_L_6TO4:
case NPC_F_LC_L_MPLS_IN_IP:
case NPC_F_LC_L_IP6_TUN_IP6:
case NPC_F_LC_L_IP6_MPLS_IN_IP:
val = npc_map2cn20k_flag(act->flags);
if (val != 0xFF)
act->flags = val;
break;
default:
break;
}
}
void
npc_cn20k_update_action_entries_n_flags(struct rvu *rvu,
struct npc_kpu_profile_adapter *pfl)
{
struct npc_kpu_profile_action *action;
int entries, ltype;
u8 flags, val;
int entries;
for (int i = 0; i < pfl->kpus; i++) {
action = pfl->kpu[i].action;
entries = pfl->kpu[i].action_entries;
for (int j = 0; j < entries; j++) {
if (action[j].lid != NPC_LID_LC)
continue;
ltype = action[j].ltype;
if (ltype != NPC_LT_LC_IP &&
ltype != NPC_LT_LC_IP6 &&
ltype != NPC_LT_LC_IP_OPT &&
ltype != NPC_LT_LC_IP6_EXT)
continue;
flags = action[j].flags;
switch (flags) {
case NPC_F_LC_U_IP_FRAG:
case NPC_F_LC_U_IP6_FRAG:
case NPC_F_LC_L_6TO4:
case NPC_F_LC_L_MPLS_IN_IP:
case NPC_F_LC_L_IP6_TUN_IP6:
case NPC_F_LC_L_IP6_MPLS_IN_IP:
val = npc_map2cn20k_flag(flags);
if (val == 0xFF) {
dev_err(rvu->dev,
"%s: Error to get flag value\n",
__func__);
return;
}
action[j].flags = val;
break;
default:
break;
}
}
for (int j = 0; j < entries; j++)
npc_cn20k_translate_action_flags(&action[j]);
}
}
@@ -1709,9 +1705,9 @@ int npc_cn20k_apply_custom_kpu(struct rvu *rvu,
for (entry = 0; entry < entries; entry++) {
profile->kpu[kpu].cam[entry] = cam[entry];
profile->kpu[kpu].action[entry] = action[entry];
npc_cn20k_translate_action_flags(&profile->kpu[kpu].action[entry]);
}
}
npc_cn20k_update_action_entries_n_flags(rvu, profile);
return 0;
}

View File

@@ -1160,7 +1160,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
err = rvu_npc_exact_init(rvu);
if (err) {
dev_err(rvu->dev, "failed to initialize exact match table\n");
return err;
goto cgx_err;
}
/* Assign MACs for CGX mapped functions */

View File

@@ -290,6 +290,7 @@ static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size)
{
int entries_per_copy = PAGE_SIZE / cqe_size;
size_t copy_bytes;
void *init_ents;
int err = 0;
int i;
@@ -314,8 +315,14 @@ static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size)
buf += PAGE_SIZE;
}
} else {
copy_bytes = array_size(entries, cqe_size);
if (WARN_ON_ONCE(copy_bytes > PAGE_SIZE)) {
err = -EINVAL;
goto out;
}
err = copy_to_user((void __user *)buf, init_ents,
array_size(entries, cqe_size)) ?
copy_bytes) ?
-EFAULT : 0;
}

View File

@@ -103,9 +103,15 @@ mlx5e_xmit_xdp_buff(struct mlx5e_xdpsq *sq, struct mlx5e_rq *rq,
xdptxd->dma_addr = dma_addr;
if (unlikely(!INDIRECT_CALL_2(sq->xmit_xdp_frame, mlx5e_xmit_xdp_frame_mpwqe,
mlx5e_xmit_xdp_frame, sq, xdptxd, 0, NULL)))
if (unlikely(!INDIRECT_CALL_2(sq->xmit_xdp_frame,
mlx5e_xmit_xdp_frame_mpwqe,
mlx5e_xmit_xdp_frame,
sq, xdptxd, 0, NULL))) {
dma_unmap_single(sq->pdev, dma_addr, xdptxd->len,
DMA_TO_DEVICE);
xdp_return_frame(xdpf);
return false;
}
/* xmit_mode == MLX5E_XDP_XMIT_MODE_FRAME */
mlx5e_xdpi_fifo_push(&sq->db.xdpi_fifo,

View File

@@ -533,23 +533,16 @@ static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
struct mlx5_vport *vport, int list_type)
{
bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
u8 (*mac_list)[ETH_ALEN];
u8 (*mac_list)[ETH_ALEN] = NULL;
struct l2addr_node *node;
struct vport_addr *addr;
struct hlist_head *hash;
struct hlist_node *tmp;
int size;
int size = 0;
int err;
int hi;
int i;
size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) :
MLX5_MAX_MC_PER_VPORT(esw->dev);
mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL);
if (!mac_list)
return;
hash = is_uc ? vport->uc_list : vport->mc_list;
for_each_l2hash_node(node, tmp, hash, hi) {
@@ -561,7 +554,7 @@ static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
goto out;
err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type,
mac_list, &size);
&mac_list, &size);
if (err)
goto out;
esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n",

View File

@@ -105,9 +105,12 @@ irq_pool_find_least_loaded(struct mlx5_irq_pool *pool, const struct cpumask *req
lockdep_assert_held(&pool->lock);
xa_for_each_range(&pool->irqs, index, iter, start, end) {
struct cpumask *iter_mask = mlx5_irq_get_affinity_mask(iter);
int iter_refcount = mlx5_irq_read_locked(iter);
const struct cpumask *iter_mask;
iter_mask = irq_get_effective_affinity_mask(mlx5_irq_get_irq(iter));
if (!iter_mask)
continue;
if (!cpumask_subset(iter_mask, req_mask))
/* skip IRQs with a mask which is not subset of req_mask */
continue;

View File

@@ -324,35 +324,63 @@ int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu)
}
EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu);
static int mlx5_vport_max_mac_list_size(struct mlx5_core_dev *dev, u16 vport,
enum mlx5_list_type list_type)
{
void *query_ctx, *hca_caps;
int ret = 0;
if (!vport && !mlx5_core_is_ecpf(dev))
return list_type == MLX5_NVPRT_LIST_TYPE_UC ?
1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
query_ctx = kzalloc(MLX5_ST_SZ_BYTES(query_hca_cap_out), GFP_KERNEL);
if (!query_ctx)
return -ENOMEM;
ret = mlx5_vport_get_other_func_general_cap(dev, vport, query_ctx);
if (ret)
goto out;
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
ret = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
1 << MLX5_GET(cmd_hca_cap, hca_caps, log_max_current_uc_list) :
1 << MLX5_GET(cmd_hca_cap, hca_caps, log_max_current_mc_list);
out:
kfree(query_ctx);
return ret;
}
int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
u16 vport,
enum mlx5_list_type list_type,
u8 addr_list[][ETH_ALEN],
int *list_size)
u8 (**addr_list)[ETH_ALEN],
int *addr_list_size)
{
u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
int allowed_list_size;
void *nic_vport_ctx;
int max_list_size;
int req_list_size;
int out_sz;
void *out;
int err;
int i;
req_list_size = *list_size;
if (!addr_list || !addr_list_size)
return -EINVAL;
max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
*addr_list = NULL;
*addr_list_size = 0;
if (req_list_size > max_list_size) {
mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
req_list_size, max_list_size);
req_list_size = max_list_size;
}
max_list_size = mlx5_vport_max_mac_list_size(dev, vport, list_type);
if (max_list_size < 0)
return max_list_size;
out_sz = MLX5_ST_SZ_BYTES(query_nic_vport_context_out) +
req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
max_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
out = kvzalloc(out_sz, GFP_KERNEL);
if (!out)
@@ -371,16 +399,24 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
nic_vport_context);
req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
allowed_list_size);
allowed_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
allowed_list_size);
if (!allowed_list_size)
goto out;
*list_size = req_list_size;
for (i = 0; i < req_list_size; i++) {
*addr_list = kcalloc(allowed_list_size, ETH_ALEN, GFP_KERNEL);
if (!*addr_list) {
err = -ENOMEM;
goto out;
}
for (i = 0; i < allowed_list_size; i++) {
u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
nic_vport_ctx,
current_uc_mac_address[i]) + 2;
ether_addr_copy(addr_list[i], mac_addr);
ether_addr_copy((*addr_list)[i], mac_addr);
}
*addr_list_size = allowed_list_size;
out:
kvfree(out);
return err;

View File

@@ -204,7 +204,7 @@ int txgbe_set_phy_link(struct wx *wx)
static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
DECLARE_PHY_INTERFACE_MASK(interfaces);
DECLARE_PHY_INTERFACE_MASK_ZERO(interfaces);
struct txgbe *txgbe = wx->priv;
if (id->cable_tech & TXGBE_SFF_DA_PASSIVE_CABLE) {
@@ -271,7 +271,7 @@ static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
static int txgbe_qsfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
DECLARE_PHY_INTERFACE_MASK(interfaces);
DECLARE_PHY_INTERFACE_MASK_ZERO(interfaces);
struct txgbe *txgbe = wx->priv;
if (id->transceiver_type & TXGBE_SFF_ETHERNET_40G_CR4) {
@@ -335,7 +335,7 @@ static int txgbe_qsfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
int txgbe_identify_module(struct wx *wx)
{
struct txgbe_hic_get_module_info buffer;
struct txgbe_hic_get_module_info buffer = { 0 };
struct txgbe_sff_id *id;
int err = 0;
u32 mod_abs;
@@ -357,18 +357,16 @@ int txgbe_identify_module(struct wx *wx)
}
id = &buffer.id;
if (id->identifier != TXGBE_SFF_IDENTIFIER_SFP &&
id->identifier != TXGBE_SFF_IDENTIFIER_QSFP &&
id->identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS &&
id->identifier != TXGBE_SFF_IDENTIFIER_QSFP28) {
wx_err(wx, "Invalid module\n");
return -ENODEV;
}
if (id->transceiver_type == 0xFF)
if (id->identifier == TXGBE_SFF_IDENTIFIER_SFP)
return txgbe_sfp_to_linkmodes(wx, id);
return txgbe_qsfp_to_linkmodes(wx, id);
if (id->identifier == TXGBE_SFF_IDENTIFIER_QSFP ||
id->identifier == TXGBE_SFF_IDENTIFIER_QSFP_PLUS ||
id->identifier == TXGBE_SFF_IDENTIFIER_QSFP28)
return txgbe_qsfp_to_linkmodes(wx, id);
wx_err(wx, "Invalid module\n");
return -EINVAL;
}
void txgbe_setup_link(struct wx *wx)

View File

@@ -315,6 +315,9 @@ void txgbe_up(struct wx *wx);
int txgbe_setup_tc(struct net_device *dev, u8 tc);
void txgbe_do_reset(struct net_device *netdev);
#define DECLARE_PHY_INTERFACE_MASK_ZERO(name) \
unsigned long name[PHY_INTERFACE_MODE_MAX] = { 0, }
#define TXGBE_LINK_SPEED_UNKNOWN 0
#define TXGBE_LINK_SPEED_10GB_FULL 4
#define TXGBE_LINK_SPEED_25GB_FULL 0x10

View File

@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/slab.h>
@@ -965,12 +966,22 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
}
for (i = 0; i < page_count; i++) {
char *src = phys_to_virt(pb[i].pfn << HV_HYP_PAGE_SHIFT);
u32 offset = pb[i].offset;
phys_addr_t paddr = (pb[i].pfn << HV_HYP_PAGE_SHIFT) +
pb[i].offset;
u32 len = pb[i].len;
memcpy(dest, (src + offset), len);
dest += len;
while (len) {
struct page *page = phys_to_page(paddr);
u32 off = offset_in_page(paddr);
u32 chunk = min_t(u32, len, PAGE_SIZE - off);
char *src = kmap_local_page(page);
memcpy(dest, src + off, chunk);
kunmap_local(src);
dest += chunk;
paddr += chunk;
len -= chunk;
}
}
if (padding)

View File

@@ -22,7 +22,6 @@
struct mctp_usb {
struct usb_device *usbdev;
struct usb_interface *intf;
bool stopped;
struct net_device *netdev;
@@ -32,6 +31,9 @@ struct mctp_usb {
struct urb *tx_urb;
struct urb *rx_urb;
/* enforces atomic access to rx_stopped and requeuing the retry work */
spinlock_t rx_lock;
bool rx_stopped;
struct delayed_work rx_retry_work;
};
@@ -122,6 +124,7 @@ static const unsigned long RX_RETRY_DELAY = HZ / 4;
static int mctp_usb_rx_queue(struct mctp_usb *mctp_usb, gfp_t gfp)
{
unsigned long flags;
struct sk_buff *skb;
int rc;
@@ -147,8 +150,11 @@ static int mctp_usb_rx_queue(struct mctp_usb *mctp_usb, gfp_t gfp)
return rc;
err_retry:
schedule_delayed_work(&mctp_usb->rx_retry_work, RX_RETRY_DELAY);
return rc;
spin_lock_irqsave(&mctp_usb->rx_lock, flags);
if (!mctp_usb->rx_stopped)
schedule_delayed_work(&mctp_usb->rx_retry_work, RX_RETRY_DELAY);
spin_unlock_irqrestore(&mctp_usb->rx_lock, flags);
return 0;
}
static void mctp_usb_in_complete(struct urb *urb)
@@ -248,9 +254,6 @@ static void mctp_usb_rx_retry_work(struct work_struct *work)
struct mctp_usb *mctp_usb = container_of(work, struct mctp_usb,
rx_retry_work.work);
if (READ_ONCE(mctp_usb->stopped))
return;
mctp_usb_rx_queue(mctp_usb, GFP_KERNEL);
}
@@ -258,7 +261,7 @@ static int mctp_usb_open(struct net_device *dev)
{
struct mctp_usb *mctp_usb = netdev_priv(dev);
WRITE_ONCE(mctp_usb->stopped, false);
WRITE_ONCE(mctp_usb->rx_stopped, false);
netif_start_queue(dev);
@@ -268,17 +271,21 @@ static int mctp_usb_open(struct net_device *dev)
static int mctp_usb_stop(struct net_device *dev)
{
struct mctp_usb *mctp_usb = netdev_priv(dev);
unsigned long flags;
netif_stop_queue(dev);
/* prevent RX submission retry */
WRITE_ONCE(mctp_usb->stopped, true);
spin_lock_irqsave(&mctp_usb->rx_lock, flags);
mctp_usb->rx_stopped = true;
cancel_delayed_work(&mctp_usb->rx_retry_work);
spin_unlock_irqrestore(&mctp_usb->rx_lock, flags);
flush_delayed_work(&mctp_usb->rx_retry_work);
usb_kill_urb(mctp_usb->rx_urb);
usb_kill_urb(mctp_usb->tx_urb);
cancel_delayed_work_sync(&mctp_usb->rx_retry_work);
return 0;
}
@@ -331,6 +338,7 @@ static int mctp_usb_probe(struct usb_interface *intf,
dev->netdev = netdev;
dev->usbdev = interface_to_usbdev(intf);
dev->intf = intf;
spin_lock_init(&dev->rx_lock);
usb_set_intfdata(intf, dev);
dev->ep_in = ep_in->bEndpointAddress;

View File

@@ -1718,6 +1718,9 @@ static int phy_sfp_probe(struct phy_device *phydev)
ret = sfp_bus_add_upstream(bus, phydev, &sfp_phydev_ops);
sfp_bus_put(bus);
if (ret)
phydev->sfp_bus = NULL;
}
if (!ret && phydev->sfp_bus)
@@ -3509,9 +3512,15 @@ static int phy_setup_ports(struct phy_device *phydev)
if (ret)
return ret;
ret = phy_sfp_probe(phydev);
if (ret)
goto out;
/* We don't support SFP with genphy drivers. Also, genphy driver
* binding occurs with RTNL help, which will deadlock the call to
* sfp_bus_add_upstream().
*/
if (!phydev->is_genphy_driven) {
ret = phy_sfp_probe(phydev);
if (ret)
goto out;
}
if (phydev->n_ports < phydev->max_n_ports) {
ret = phy_default_setup_single_port(phydev);
@@ -3775,6 +3784,11 @@ static int phy_probe(struct device *dev)
return 0;
out:
sfp_bus_del_upstream(phydev->sfp_bus);
phydev->sfp_bus = NULL;
phy_cleanup_ports(phydev);
if (!phydev->is_on_sfp_module)
phy_led_triggers_unregister(phydev);
@@ -3798,11 +3812,11 @@ static int phy_remove(struct device *dev)
phydev->state = PHY_DOWN;
phy_cleanup_ports(phydev);
sfp_bus_del_upstream(phydev->sfp_bus);
phydev->sfp_bus = NULL;
phy_cleanup_ports(phydev);
if (phydev->drv && phydev->drv->remove)
phydev->drv->remove(phydev);

View File

@@ -2070,6 +2070,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
struct virtio_net_hdr_v1_hash_tunnel hdr;
struct virtio_net_hdr *gso;
memset(&hdr, 0, sizeof(hdr));
ret = tun_vnet_hdr_tnl_from_skb(tun->flags, tun->dev, skb,
&hdr);
if (ret)

View File

@@ -9851,7 +9851,12 @@ static int rtl8152_probe_once(struct usb_interface *intf,
struct net_device *netdev;
int ret;
usb_reset_device(udev);
ret = usb_reset_device(udev);
if (ret < 0) {
dev_err(&intf->dev, "USB reset failed, errno=%d\n", ret);
return ret;
}
netdev = alloc_etherdev(sizeof(struct r8152));
if (!netdev) {
dev_err(&intf->dev, "Out of memory\n");

View File

@@ -1468,18 +1468,16 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np);
of_node_put(cell_np);
if (!cell_entry) {
__nvmem_device_put(nvmem);
nvmem_layout_module_put(nvmem);
if (nvmem->layout)
return ERR_PTR(-EPROBE_DEFER);
else
return ERR_PTR(-ENOENT);
ret = nvmem->layout ? -EPROBE_DEFER : -ENOENT;
__nvmem_device_put(nvmem);
return ERR_PTR(ret);
}
cell = nvmem_create_cell(cell_entry, id, cell_index);
if (IS_ERR(cell)) {
__nvmem_device_put(nvmem);
nvmem_layout_module_put(nvmem);
__nvmem_device_put(nvmem);
}
return cell;
@@ -1593,8 +1591,8 @@ void nvmem_cell_put(struct nvmem_cell *cell)
kfree_const(cell->id);
kfree(cell);
__nvmem_device_put(nvmem);
nvmem_layout_module_put(nvmem);
__nvmem_device_put(nvmem);
}
EXPORT_SYMBOL_GPL(nvmem_cell_put);

View File

@@ -119,7 +119,7 @@ static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem,
cell.name = onie_tlv_cell_name(tlv.type);
if (!cell.name)
continue;
goto next;
cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len);
cell.bytes = tlv.len;
@@ -132,6 +132,7 @@ static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem,
return ret;
}
next:
offset += sizeof(tlv) + tlv.len;
}

View File

@@ -26,7 +26,6 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/dmi.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/string_choices.h>
@@ -40,39 +39,6 @@
static struct amd_gpio *pinctrl_dev;
#endif
static const struct dmi_system_id amd_gpio_quirk_yoga7_14agp11[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "83TD"),
DMI_MATCH(DMI_BOARD_NAME, "LNVNB161216"),
},
},
{ }
};
static void amd_gpio_apply_quirks(struct amd_gpio *gpio_dev)
{
const unsigned int pin = 157; /* WACF2200 GpioInt per ACPI _CRS */
unsigned long flags;
u32 reg;
if (!dmi_check_system(amd_gpio_quirk_yoga7_14agp11))
return;
if (pin >= gpio_dev->gc.ngpio)
return;
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
reg = readl(gpio_dev->base + pin * 4);
reg |= BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
writel(reg, gpio_dev->base + pin * 4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
dev_info(&gpio_dev->pdev->dev,
"Enabled IRQ for GPIO %u (Yoga 7 14AGP11 touchscreen)\n",
pin);
}
static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
{
unsigned long flags;
@@ -1253,7 +1219,6 @@ static int amd_gpio_probe(struct platform_device *pdev)
/* Disable and mask interrupts */
amd_gpio_irq_init(gpio_dev);
amd_gpio_apply_quirks(gpio_dev);
girq = &gpio_dev->gc.irq;
gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip);

View File

@@ -10,6 +10,7 @@
#include "pinctrl-mcp23s08.h"
#define MCP_MAX_DEV_PER_CS 8
#define MCP23S08_SPI_BASE 0x40
/*
* A given spi_device can represent up to eight mcp23sxx chips
@@ -143,13 +144,13 @@ static int mcp23s08_probe(struct spi_device *spi)
unsigned int addr;
int chips;
int ret;
u32 v;
u8 v;
info = spi_get_device_match_data(spi);
ret = device_property_read_u32(dev, "microchip,spi-present-mask", &v);
ret = device_property_read_u8(dev, "microchip,spi-present-mask", &v);
if (ret) {
ret = device_property_read_u32(dev, "mcp,spi-present-mask", &v);
ret = device_property_read_u8(dev, "mcp,spi-present-mask", &v);
if (ret) {
dev_err(dev, "missing spi-present-mask");
return ret;
@@ -173,6 +174,8 @@ static int mcp23s08_probe(struct spi_device *spi)
for_each_set_bit(addr, &spi_present_mask, MCP_MAX_DEV_PER_CS) {
data->mcp[addr] = &data->chip[--chips];
data->mcp[addr]->irq = spi->irq;
data->mcp[addr]->dev = dev;
data->mcp[addr]->addr = MCP23S08_SPI_BASE | (addr << 1);
ret = mcp23s08_spi_regmap_init(data->mcp[addr], dev, addr, info);
if (ret)
@@ -184,7 +187,7 @@ static int mcp23s08_probe(struct spi_device *spi)
if (!data->mcp[addr]->pinctrl_desc.name)
return -ENOMEM;
ret = mcp23s08_probe_one(data->mcp[addr], dev, 0x40 | (addr << 1),
ret = mcp23s08_probe_one(data->mcp[addr], dev, MCP23S08_SPI_BASE | (addr << 1),
info->type, -1);
if (ret < 0)
return ret;

View File

@@ -487,7 +487,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
domain->ipg_rate_mhz = ipg_rate_mhz;
pd_pdev->dev.parent = &pdev->dev;
pd_pdev->dev.of_node = np;
pd_pdev->dev.of_node = of_node_get(np);
pd_pdev->dev.fwnode = of_fwnode_handle(np);
ret = platform_device_add(pd_pdev);

View File

@@ -86,7 +86,7 @@ static inline void ti_sci_pd_set_wkup_constraint(struct device *dev)
const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
int ret;
if (device_may_wakeup(dev)) {
if (device_may_wakeup(dev) || device_wakeup_path(dev)) {
/*
* If device can wakeup using IO daisy chain wakeups,
* we do not want to set a constraint.

View File

@@ -2479,8 +2479,13 @@ ptp_ocp_ts_enable(void *priv, u32 req, bool enable)
iowrite32(1, &reg->intr_mask);
iowrite32(1, &reg->intr);
} else {
int irq_vec = pci_irq_vector(bp->pdev, ext->irq_vec);
iowrite32(0, &reg->intr_mask);
iowrite32(0, &reg->enable);
ioread32(&reg->intr_mask);
if (irq_vec > 0)
synchronize_irq(irq_vec);
}
return 0;
@@ -4867,6 +4872,22 @@ ptp_ocp_detach(struct ptp_ocp *bp)
ptp_ocp_detach_sysfs(bp);
ptp_ocp_attr_group_del(bp);
timer_delete_sync(&bp->watchdog);
/* Disable interrupts on all timestampers */
if (bp->ts0)
ptp_ocp_ts_enable(bp->ts0, 0, false);
if (bp->ts1)
ptp_ocp_ts_enable(bp->ts1, 0, false);
if (bp->ts2)
ptp_ocp_ts_enable(bp->ts2, 0, false);
if (bp->ts3)
ptp_ocp_ts_enable(bp->ts3, 0, false);
if (bp->ts4)
ptp_ocp_ts_enable(bp->ts4, 0, false);
if (bp->pps)
ptp_ocp_ts_enable(bp->pps, ~0, false);
if (bp->ptp)
ptp_clock_unregister(bp->ptp);
kfree(bp->ptp_info.pin_config);
ptp_ocp_unregister_ext(bp->ts0);
ptp_ocp_unregister_ext(bp->ts1);
ptp_ocp_unregister_ext(bp->ts2);
@@ -4884,9 +4905,6 @@ ptp_ocp_detach(struct ptp_ocp *bp)
clk_hw_unregister_fixed_rate(bp->i2c_clk);
if (bp->n_irqs)
pci_free_irq_vectors(bp->pdev);
if (bp->ptp)
ptp_clock_unregister(bp->ptp);
kfree(bp->ptp_info.pin_config);
device_unregister(&bp->dev);
}

View File

@@ -1471,15 +1471,12 @@ static int qcom_slim_ngd_ssr_pdr_notify(struct qcom_slim_ngd_ctrl *ctrl,
switch (action) {
case QCOM_SSR_BEFORE_SHUTDOWN:
case SERVREG_SERVICE_STATE_DOWN:
/* Make sure the last dma xfer is finished */
mutex_lock(&ctrl->tx_lock);
if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN) {
pm_runtime_get_noresume(ctrl->ctrl.dev);
ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
qcom_slim_ngd_down(ctrl);
qcom_slim_ngd_exit_dma(ctrl);
}
mutex_unlock(&ctrl->tx_lock);
break;
case QCOM_SSR_AFTER_POWERUP:
case SERVREG_SERVICE_STATE_UP:
@@ -1542,7 +1539,7 @@ static int of_qcom_slim_ngd_register(struct device *parent,
kfree(ngd);
return ret;
}
ngd->pdev->dev.of_node = node;
ngd->pdev->dev.of_node = of_node_get(node);
ctrl->ngd = ngd;
ret = platform_device_add(ngd->pdev);
@@ -1560,6 +1557,13 @@ static int of_qcom_slim_ngd_register(struct device *parent,
return -ENODEV;
}
static void qcom_slim_ngd_unregister(struct qcom_slim_ngd_ctrl *ctrl)
{
struct qcom_slim_ngd *ngd = ctrl->ngd;
platform_device_del(ngd->pdev);
}
static int qcom_slim_ngd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1577,24 +1581,10 @@ static int qcom_slim_ngd_probe(struct platform_device *pdev)
ret = qcom_slim_ngd_qmi_svc_event_init(ctrl);
if (ret) {
dev_err(&pdev->dev, "QMI service registration failed:%d", ret);
return ret;
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev);
}
INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
INIT_WORK(&ctrl->ngd_up_work, qcom_slim_ngd_up_worker);
ctrl->mwq = create_singlethread_workqueue("ngd_master");
if (!ctrl->mwq) {
dev_err(&pdev->dev, "Failed to start master worker\n");
ret = -ENOMEM;
goto wq_err;
}
return 0;
wq_err:
qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
if (ctrl->mwq)
destroy_workqueue(ctrl->mwq);
return ret;
}
@@ -1602,6 +1592,7 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct qcom_slim_ngd_ctrl *ctrl;
int irq;
int ret;
struct pdr_service *pds;
@@ -1615,20 +1606,16 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
if (IS_ERR(ctrl->base))
return PTR_ERR(ctrl->base);
ret = platform_get_irq(pdev, 0);
if (ret < 0)
return ret;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
ret = devm_request_irq(dev, ret, qcom_slim_ngd_interrupt,
IRQF_TRIGGER_HIGH, "slim-ngd", ctrl);
ret = devm_request_irq(dev, irq, qcom_slim_ngd_interrupt,
IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN,
"slim-ngd", ctrl);
if (ret)
return dev_err_probe(&pdev->dev, ret, "request IRQ failed\n");
ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
ctrl->notifier = qcom_register_ssr_notifier("lpass", &ctrl->nb);
if (IS_ERR(ctrl->notifier))
return PTR_ERR(ctrl->notifier);
ctrl->dev = dev;
ctrl->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
ctrl->framer.superfreq =
@@ -1649,48 +1636,71 @@ static int qcom_slim_ngd_ctrl_probe(struct platform_device *pdev)
init_completion(&ctrl->qmi.qmi_comp);
init_completion(&ctrl->qmi_up);
INIT_WORK(&ctrl->m_work, qcom_slim_ngd_master_worker);
INIT_WORK(&ctrl->ngd_up_work, qcom_slim_ngd_up_worker);
ctrl->mwq = create_singlethread_workqueue("ngd_master");
if (!ctrl->mwq)
return dev_err_probe(dev, -ENOMEM, "Failed to start master worker\n");
ctrl->pdr = pdr_handle_alloc(slim_pd_status, ctrl);
if (IS_ERR(ctrl->pdr)) {
ret = dev_err_probe(dev, PTR_ERR(ctrl->pdr),
"Failed to init PDR handle\n");
goto err_pdr_alloc;
ret = dev_err_probe(dev, PTR_ERR(ctrl->pdr), "Failed to init PDR handle\n");
goto err_destroy_mwq;
}
ret = of_qcom_slim_ngd_register(dev, ctrl);
if (ret)
goto err_pdr_release;
pds = pdr_add_lookup(ctrl->pdr, "avs/audio", "msm/adsp/audio_pd");
if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
ret = dev_err_probe(dev, PTR_ERR(pds), "pdr add lookup failed\n");
goto err_pdr_lookup;
goto err_unregister_ngd;
}
platform_driver_register(&qcom_slim_ngd_driver);
return of_qcom_slim_ngd_register(dev, ctrl);
ctrl->nb.notifier_call = qcom_slim_ngd_ssr_notify;
ctrl->notifier = qcom_register_ssr_notifier("lpass", &ctrl->nb);
if (IS_ERR(ctrl->notifier)) {
ret = PTR_ERR(ctrl->notifier);
goto err_unregister_ngd;
}
err_pdr_alloc:
qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
enable_irq(irq);
err_pdr_lookup:
return 0;
err_unregister_ngd:
qcom_slim_ngd_unregister(ctrl);
err_pdr_release:
pdr_handle_release(ctrl->pdr);
err_destroy_mwq:
destroy_workqueue(ctrl->mwq);
return ret;
}
static void qcom_slim_ngd_ctrl_remove(struct platform_device *pdev)
{
platform_driver_unregister(&qcom_slim_ngd_driver);
struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
pdr_handle_release(ctrl->pdr);
qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
qcom_slim_ngd_unregister(ctrl);
destroy_workqueue(ctrl->mwq);
}
static void qcom_slim_ngd_remove(struct platform_device *pdev)
{
struct qcom_slim_ngd_ctrl *ctrl = platform_get_drvdata(pdev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pdr_handle_release(ctrl->pdr);
qcom_unregister_ssr_notifier(ctrl->notifier, &ctrl->nb);
qcom_slim_ngd_enable(ctrl, false);
qcom_slim_ngd_exit_dma(ctrl);
qcom_slim_ngd_qmi_svc_event_deinit(&ctrl->qmi);
if (ctrl->mwq)
destroy_workqueue(ctrl->mwq);
kfree(ctrl->ngd);
ctrl->ngd = NULL;
@@ -1752,6 +1762,28 @@ static struct platform_driver qcom_slim_ngd_driver = {
},
};
module_platform_driver(qcom_slim_ngd_ctrl_driver);
static int qcom_slim_ngd_init(void)
{
int ret;
ret = platform_driver_register(&qcom_slim_ngd_driver);
if (ret)
return ret;
ret = platform_driver_register(&qcom_slim_ngd_ctrl_driver);
if (ret)
platform_driver_unregister(&qcom_slim_ngd_driver);
return ret;
}
static void qcom_slim_ngd_exit(void)
{
platform_driver_unregister(&qcom_slim_ngd_ctrl_driver);
platform_driver_unregister(&qcom_slim_ngd_driver);
}
module_init(qcom_slim_ngd_init);
module_exit(qcom_slim_ngd_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Qualcomm SLIMBus NGD controller");

View File

@@ -158,8 +158,8 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
of_data = (struct mpfs_syscon_config *) device_get_match_data(dev);
if (!of_data) {
dev_err(dev, "Error getting match data\n");
return -EINVAL;
ret = dev_err_probe(dev, -EINVAL, "Error getting match data\n");
goto out_free_channel;
}
for (i = 0; i < of_data->nb_subdevs; i++) {
@@ -173,6 +173,8 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
return 0;
out_free_channel:
mbox_free_channel(sys_controller->chan);
out_free:
kfree(sys_controller);
return ret;

View File

@@ -472,7 +472,9 @@ static inline void dw_spi_abort(struct spi_controller *ctlr)
if (dws->dma_mapped)
dws->dma_ops->dma_stop(dws);
disable_irq(dws->irq);
dw_spi_reset_chip(dws);
enable_irq(dws->irq);
}
static void dw_spi_handle_err(struct spi_controller *ctlr,

View File

@@ -440,10 +440,15 @@ static int setup_gsi_xfer(struct spi_transfer *xfer, struct spi_geni_master *mas
return ret;
}
if (!xfer->cs_change) {
if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
peripheral.fragmentation = FRAGMENTATION;
}
/*
* Set fragmentation to keep CS asserted after this transfer when:
* - non-last transfer with cs_change=0: keep CS asserted between chained transfers
* - last transfer with cs_change=1: keep CS asserted after the message
* (e.g. TPM TIS SPI uses cs_change=1 on single-transfer messages to
* keep CS asserted across header, wait-state and data phases)
*/
peripheral.fragmentation = list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers) ?
xfer->cs_change : !xfer->cs_change;
if (peripheral.cmd & SPI_RX) {
dmaengine_slave_config(mas->rx, &config);
@@ -849,10 +854,16 @@ static int setup_se_xfer(struct spi_transfer *xfer,
mas->cur_xfer_mode = GENI_SE_DMA;
geni_se_select_mode(se, mas->cur_xfer_mode);
if (!xfer->cs_change) {
if (!list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers))
m_params = FRAGMENTATION;
}
/*
* Set FRAGMENTATION to keep CS asserted after this transfer when:
* - non-last transfer with cs_change=0: keep CS asserted between chained transfers
* - last transfer with cs_change=1: keep CS asserted after the message
* (e.g. TPM TIS SPI uses cs_change=1 on single-transfer messages to
* keep CS asserted across header, wait-state and data phases)
*/
if (list_is_last(&xfer->transfer_list, &spi->cur_msg->transfers) ?
xfer->cs_change : !xfer->cs_change)
m_params = FRAGMENTATION;
/*
* Lock around right before we start the transfer since our

View File

@@ -135,8 +135,9 @@ static inline void rzv2h_rspi_rx_##type(struct rzv2h_rspi_priv *rspi, \
RZV2H_RSPI_TX(writel, u32)
RZV2H_RSPI_TX(writew, u16)
RZV2H_RSPI_TX(writeb, u8)
/* The read access size for RSPI_SPDR is fixed at 32 bits */
RZV2H_RSPI_RX(readl, u32)
RZV2H_RSPI_RX(readw, u16)
RZV2H_RSPI_RX(readl, u16)
RZV2H_RSPI_RX(readl, u8)
static void rzv2h_rspi_reg_rmw(const struct rzv2h_rspi_priv *rspi,

View File

@@ -464,8 +464,11 @@ static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex
if (check_fwstate(pmlmepriv, _FW_LINKED) && (is_same_network(&pmlmepriv->cur_network.network, pnetwork, 0))) {
update_network(&pmlmepriv->cur_network.network, pnetwork, adapter, true);
if (pmlmepriv->cur_network.network.ie_length < sizeof(struct ndis_802_11_fix_ie))
return;
rtw_update_protection(adapter, (pmlmepriv->cur_network.network.ies) + sizeof(struct ndis_802_11_fix_ie),
pmlmepriv->cur_network.network.ie_length);
pmlmepriv->cur_network.network.ie_length - sizeof(struct ndis_802_11_fix_ie));
}
}
@@ -601,6 +604,8 @@ static bool rtw_is_desired_network(struct adapter *adapter, struct wlan_network
privacy = pnetwork->network.privacy;
if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
if (pnetwork->network.ie_length < _FIXED_IE_LENGTH_)
return false;
if (rtw_get_wps_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, pnetwork->network.ie_length - _FIXED_IE_LENGTH_, NULL, &wps_ielen))
return true;
else
@@ -614,11 +619,15 @@ static bool rtw_is_desired_network(struct adapter *adapter, struct wlan_network
bselected = false;
if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
p = rtw_get_ie(pnetwork->network.ies + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len, (pnetwork->network.ie_length - _BEACON_IE_OFFSET_));
if (p && ie_len > 0)
bselected = true;
else
if (pnetwork->network.ie_length < _BEACON_IE_OFFSET_) {
bselected = false;
} else {
p = rtw_get_ie(pnetwork->network.ies + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len, (pnetwork->network.ie_length - _BEACON_IE_OFFSET_));
if (p && ie_len > 0)
bselected = true;
else
bselected = false;
}
}
}
@@ -1072,8 +1081,11 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
break;
}
if (cur_network->network.ie_length < sizeof(struct ndis_802_11_fix_ie))
return;
rtw_update_protection(padapter, (cur_network->network.ies) + sizeof(struct ndis_802_11_fix_ie),
(cur_network->network.ie_length));
(cur_network->network.ie_length - sizeof(struct ndis_802_11_fix_ie)));
rtw_update_ht_cap(padapter, cur_network->network.ies, cur_network->network.ie_length, (u8) cur_network->network.configuration.ds_config);
}

View File

@@ -60,6 +60,8 @@ static bool tb_property_entry_valid(const struct tb_property_entry *entry,
case TB_PROPERTY_TYPE_DIRECTORY:
case TB_PROPERTY_TYPE_DATA:
case TB_PROPERTY_TYPE_TEXT:
if (!entry->length)
return false;
if (entry->length > block_len)
return false;
if (check_add_overflow(entry->value, entry->length, &end) ||
@@ -185,6 +187,10 @@ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
if (is_root) {
content_offset = dir_offset + 2;
content_len = dir_len;
if (content_offset + content_len > block_len) {
tb_property_free_dir(dir);
return NULL;
}
} else {
if (dir_len < 4) {
tb_property_free_dir(dir);

View File

@@ -55,6 +55,7 @@ static const char * const state_names[] = {
struct xdomain_request_work {
struct work_struct work;
struct tb_xdp_header *pkg;
size_t pkg_len;
struct tb *tb;
};
@@ -122,7 +123,9 @@ static bool tb_xdomain_match(const struct tb_cfg_request *req,
static bool tb_xdomain_copy(struct tb_cfg_request *req,
const struct ctl_pkg *pkg)
{
memcpy(req->response, pkg->buffer, req->response_size);
size_t len = min_t(size_t, pkg->frame.size, req->response_size);
memcpy(req->response, pkg->buffer, len);
req->result.err = 0;
return true;
}
@@ -393,6 +396,8 @@ static int tb_xdp_properties_request(struct tb_ctl *ctl, u64 route,
}
}
if (req.offset + len > data_len)
len = data_len - req.offset;
memcpy(data + req.offset, res->data, len * 4);
req.offset += len;
} while (!data_len || req.offset < data_len);
@@ -731,6 +736,7 @@ static void tb_xdp_handle_request(struct work_struct *work)
struct xdomain_request_work *xw = container_of(work, typeof(*xw), work);
const struct tb_xdp_header *pkg = xw->pkg;
const struct tb_xdomain_header *xhdr = &pkg->xd_hdr;
size_t pkg_len = xw->pkg_len;
struct tb *tb = xw->tb;
struct tb_ctl *ctl = tb->ctl;
struct tb_xdomain *xd;
@@ -762,7 +768,7 @@ static void tb_xdp_handle_request(struct work_struct *work)
switch (pkg->type) {
case PROPERTIES_REQUEST:
tb_dbg(tb, "%llx: received XDomain properties request\n", route);
if (xd) {
if (xd && pkg_len >= sizeof(struct tb_xdp_properties)) {
ret = tb_xdp_properties_response(tb, ctl, xd, sequence,
(const struct tb_xdp_properties *)pkg);
}
@@ -816,7 +822,8 @@ static void tb_xdp_handle_request(struct work_struct *work)
tb_dbg(tb, "%llx: received XDomain link state change request\n",
route);
if (xd && xd->state == XDOMAIN_STATE_BONDING_UUID_HIGH) {
if (xd && xd->state == XDOMAIN_STATE_BONDING_UUID_HIGH &&
pkg_len >= sizeof(struct tb_xdp_link_state_change)) {
const struct tb_xdp_link_state_change *lsc =
(const struct tb_xdp_link_state_change *)pkg;
@@ -868,6 +875,7 @@ tb_xdp_schedule_request(struct tb *tb, const struct tb_xdp_header *hdr,
kfree(xw);
return false;
}
xw->pkg_len = size;
xw->tb = tb_domain_get(tb);
schedule_work(&xw->work);

View File

@@ -773,6 +773,12 @@ static int get_manuf_info(struct edgeport_serial *serial, u8 *buffer)
}
/* Read the descriptor data */
if (le16_to_cpu(rom_desc->Size) != sizeof(struct edge_ti_manuf_descriptor)) {
dev_err(dev, "unexpected Edge descriptor length: %u\n",
le16_to_cpu(rom_desc->Size));
status = -EINVAL;
goto exit;
}
status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc),
le16_to_cpu(rom_desc->Size), buffer);
if (status)
@@ -838,6 +844,11 @@ static int build_i2c_fw_hdr(u8 *header, const struct firmware *fw)
/* Pointer to fw_down memory image */
img_header = (struct ti_i2c_image_header *)&fw->data[4];
if (le16_to_cpu(img_header->Length) >
buffer_size - sizeof(struct ti_i2c_firmware_rec)) {
kfree(buffer);
return -EINVAL;
}
memcpy(buffer + sizeof(struct ti_i2c_firmware_rec),
&fw->data[4 + sizeof(struct ti_i2c_image_header)],
le16_to_cpu(img_header->Length));

View File

@@ -330,8 +330,8 @@ static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
unsigned char *buf = dest;
int count;
count = kfifo_out_locked(&port->write_fifo, buf + KLSI_HDR_LEN, size,
&port->lock);
count = kfifo_out_locked(&port->write_fifo, buf + KLSI_HDR_LEN,
size - KLSI_HDR_LEN, &port->lock);
put_unaligned_le16(count, buf);
return count + KLSI_HDR_LEN;

View File

@@ -202,6 +202,7 @@ static void option_instat_callback(struct urb *urb);
#define DELL_PRODUCT_5821E_ESIM 0x81e0
#define DELL_PRODUCT_5829E_ESIM 0x81e4
#define DELL_PRODUCT_5829E 0x81e6
#define DELL_PRODUCT_5826E_ESIM 0x81ea
#define DELL_PRODUCT_FM101R_ESIM 0x8213
#define DELL_PRODUCT_FM101R 0x8215
@@ -1123,6 +1124,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(0) | RSVD(6) },
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5829E_ESIM),
.driver_info = RSVD(0) | RSVD(6) },
{ USB_DEVICE_INTERFACE_CLASS(DELL_VENDOR_ID, DELL_PRODUCT_5826E_ESIM, 0xff),
.driver_info = RSVD(1) | RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(DELL_VENDOR_ID, DELL_PRODUCT_FM101R, 0xff) },
{ USB_DEVICE_INTERFACE_CLASS(DELL_VENDOR_ID, DELL_PRODUCT_FM101R_ESIM, 0xff) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */

View File

@@ -29,6 +29,8 @@
#ifndef DRM_ATOMIC_UAPI_H_
#define DRM_ATOMIC_UAPI_H_
#include <linux/types.h>
struct drm_crtc_state;
struct drm_display_mode;
struct drm_property_blob;
@@ -50,7 +52,7 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
struct drm_crtc *crtc);
void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
struct drm_framebuffer *fb);
void drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
bool drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
struct drm_colorop *colorop);
int __must_check
drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,

Some files were not shown because too many files have changed in this diff Show More