mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
Merge tag 'v6.6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into odroid-6.6.y
This is the 6.6.17 stable release Change-Id: I46202f4caba1513111a4b578884fc054ea992e56
This commit is contained in:
@@ -31,7 +31,7 @@ you probably needn't concern yourself with pcmciautils.
|
||||
====================== =============== ========================================
|
||||
GNU C 5.1 gcc --version
|
||||
Clang/LLVM (optional) 11.0.0 clang --version
|
||||
Rust (optional) 1.71.1 rustc --version
|
||||
Rust (optional) 1.73.0 rustc --version
|
||||
bindgen (optional) 0.65.1 bindgen --version
|
||||
GNU make 3.82 make --version
|
||||
bash 4.2 bash --version
|
||||
|
||||
@@ -23635,6 +23635,7 @@ F: include/xen/arm/swiotlb-xen.h
|
||||
F: include/xen/swiotlb-xen.h
|
||||
|
||||
XFS FILESYSTEM
|
||||
M: Catherine Hoang <catherine.hoang@oracle.com>
|
||||
M: Chandan Babu R <chandan.babu@oracle.com>
|
||||
R: Darrick J. Wong <djwong@kernel.org>
|
||||
L: linux-xfs@vger.kernel.org
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 16
|
||||
SUBLEVEL = 17
|
||||
EXTRAVERSION =
|
||||
NAME = Hurr durr I'ma ninja sloth
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ void dma_cache_wback(phys_addr_t start, unsigned long sz);
|
||||
|
||||
/* TBD: optimize this */
|
||||
#define flush_cache_vmap(start, end) flush_cache_all()
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) flush_cache_all()
|
||||
|
||||
#define flush_cache_dup_mm(mm) /* called on fork (VIVT only) */
|
||||
|
||||
@@ -340,6 +340,8 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end)
|
||||
dsb(ishst);
|
||||
}
|
||||
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
|
||||
static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (!cache_is_vipt_nonaliasing())
|
||||
|
||||
@@ -43,6 +43,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
|
||||
*/
|
||||
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
|
||||
#define flush_cache_vmap(start, end) cache_wbinv_all()
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) cache_wbinv_all()
|
||||
|
||||
#define flush_icache_range(start, end) cache_wbinv_range(start, end)
|
||||
|
||||
@@ -41,6 +41,7 @@ void flush_icache_mm_range(struct mm_struct *mm,
|
||||
void flush_icache_deferred(struct mm_struct *mm);
|
||||
|
||||
#define flush_cache_vmap(start, end) do { } while (0)
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) do { } while (0)
|
||||
|
||||
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
||||
|
||||
@@ -191,6 +191,7 @@ extern void cache_push_v(unsigned long vaddr, int len);
|
||||
#define flush_cache_all() __flush_cache_all()
|
||||
|
||||
#define flush_cache_vmap(start, end) flush_cache_all()
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) flush_cache_all()
|
||||
|
||||
static inline void flush_cache_mm(struct mm_struct *mm)
|
||||
|
||||
@@ -97,6 +97,8 @@ static inline void flush_cache_vmap(unsigned long start, unsigned long end)
|
||||
__flush_cache_vmap();
|
||||
}
|
||||
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
|
||||
extern void (*__flush_cache_vunmap)(void);
|
||||
|
||||
static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
|
||||
|
||||
@@ -38,6 +38,7 @@ void flush_icache_pages(struct vm_area_struct *vma, struct page *page,
|
||||
#define flush_icache_pages flush_icache_pages
|
||||
|
||||
#define flush_cache_vmap(start, end) flush_dcache_range(start, end)
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) flush_dcache_range(start, end)
|
||||
|
||||
extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
|
||||
|
||||
@@ -41,6 +41,7 @@ void flush_kernel_vmap_range(void *vaddr, int size);
|
||||
void invalidate_kernel_vmap_range(void *vaddr, int size);
|
||||
|
||||
#define flush_cache_vmap(start, end) flush_cache_all()
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) flush_cache_all()
|
||||
|
||||
void flush_dcache_folio(struct folio *folio);
|
||||
|
||||
@@ -37,7 +37,8 @@ static inline void flush_dcache_page(struct page *page)
|
||||
flush_icache_mm(vma->vm_mm, 0)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end)
|
||||
#define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end)
|
||||
#define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
|
||||
@@ -11,6 +11,9 @@ static inline void arch_clear_hugepage_flags(struct page *page)
|
||||
}
|
||||
#define arch_clear_hugepage_flags arch_clear_hugepage_flags
|
||||
|
||||
bool arch_hugetlb_migration_supported(struct hstate *h);
|
||||
#define arch_hugetlb_migration_supported arch_hugetlb_migration_supported
|
||||
|
||||
#ifdef CONFIG_RISCV_ISA_SVNAPOT
|
||||
#define __HAVE_ARCH_HUGE_PTE_CLEAR
|
||||
void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||
|
||||
@@ -273,9 +273,6 @@ void sbi_set_timer(uint64_t stime_value);
|
||||
void sbi_shutdown(void);
|
||||
void sbi_send_ipi(unsigned int cpu);
|
||||
int sbi_remote_fence_i(const struct cpumask *cpu_mask);
|
||||
int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
|
||||
unsigned long start,
|
||||
unsigned long size);
|
||||
|
||||
int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
|
||||
unsigned long start,
|
||||
|
||||
@@ -21,4 +21,9 @@ static inline bool on_thread_stack(void)
|
||||
return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1));
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_VMAP_STACK
|
||||
DECLARE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack);
|
||||
#endif /* CONFIG_VMAP_STACK */
|
||||
|
||||
#endif /* _ASM_RISCV_STACKTRACE_H */
|
||||
|
||||
@@ -15,7 +15,13 @@ static void tlb_flush(struct mmu_gather *tlb);
|
||||
|
||||
static inline void tlb_flush(struct mmu_gather *tlb)
|
||||
{
|
||||
flush_tlb_mm(tlb->mm);
|
||||
#ifdef CONFIG_MMU
|
||||
if (tlb->fullmm || tlb->need_flush_all || tlb->freed_tables)
|
||||
flush_tlb_mm(tlb->mm);
|
||||
else
|
||||
flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end,
|
||||
tlb_get_unmap_size(tlb));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _ASM_RISCV_TLB_H */
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <asm/smp.h>
|
||||
#include <asm/errata_list.h>
|
||||
|
||||
#define FLUSH_TLB_MAX_SIZE ((unsigned long)-1)
|
||||
#define FLUSH_TLB_NO_ASID ((unsigned long)-1)
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
extern unsigned long asid_mask;
|
||||
|
||||
@@ -32,9 +35,13 @@ static inline void local_flush_tlb_page(unsigned long addr)
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_MMU)
|
||||
void flush_tlb_all(void);
|
||||
void flush_tlb_mm(struct mm_struct *mm);
|
||||
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, unsigned int page_size);
|
||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
|
||||
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end);
|
||||
void flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||
void local_flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
|
||||
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
@@ -51,14 +58,16 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
#define flush_tlb_mm(mm) flush_tlb_all()
|
||||
#endif /* !CONFIG_SMP || !CONFIG_MMU */
|
||||
|
||||
/* Flush a range of kernel pages */
|
||||
static inline void flush_tlb_kernel_range(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
flush_tlb_all();
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
#define flush_tlb_mm(mm) flush_tlb_all()
|
||||
#define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all()
|
||||
#define local_flush_tlb_kernel_range(start, end) flush_tlb_all()
|
||||
#endif /* !CONFIG_SMP || !CONFIG_MMU */
|
||||
|
||||
#endif /* _ASM_RISCV_TLBFLUSH_H */
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/reboot.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
/* default SBI version is 0.1 */
|
||||
unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
|
||||
@@ -376,32 +377,15 @@ int sbi_remote_fence_i(const struct cpumask *cpu_mask)
|
||||
}
|
||||
EXPORT_SYMBOL(sbi_remote_fence_i);
|
||||
|
||||
/**
|
||||
* sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote
|
||||
* harts for the specified virtual address range.
|
||||
* @cpu_mask: A cpu mask containing all the target harts.
|
||||
* @start: Start of the virtual address
|
||||
* @size: Total size of the virtual address range.
|
||||
*
|
||||
* Return: 0 on success, appropriate linux error code otherwise.
|
||||
*/
|
||||
int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
|
||||
unsigned long start,
|
||||
unsigned long size)
|
||||
{
|
||||
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
|
||||
cpu_mask, start, size, 0, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(sbi_remote_sfence_vma);
|
||||
|
||||
/**
|
||||
* sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given
|
||||
* remote harts for a virtual address range belonging to a specific ASID.
|
||||
* remote harts for a virtual address range belonging to a specific ASID or not.
|
||||
*
|
||||
* @cpu_mask: A cpu mask containing all the target harts.
|
||||
* @start: Start of the virtual address
|
||||
* @size: Total size of the virtual address range.
|
||||
* @asid: The value of address space identifier (ASID).
|
||||
* @asid: The value of address space identifier (ASID), or FLUSH_TLB_NO_ASID
|
||||
* for flushing all address spaces.
|
||||
*
|
||||
* Return: 0 on success, appropriate linux error code otherwise.
|
||||
*/
|
||||
@@ -410,8 +394,12 @@ int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
|
||||
unsigned long size,
|
||||
unsigned long asid)
|
||||
{
|
||||
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
|
||||
cpu_mask, start, size, asid, 0);
|
||||
if (asid == FLUSH_TLB_NO_ASID)
|
||||
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
|
||||
cpu_mask, start, size, 0, 0);
|
||||
else
|
||||
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
|
||||
cpu_mask, start, size, asid, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(sbi_remote_sfence_vma_asid);
|
||||
|
||||
|
||||
@@ -125,6 +125,26 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
|
||||
return pte;
|
||||
}
|
||||
|
||||
unsigned long hugetlb_mask_last_page(struct hstate *h)
|
||||
{
|
||||
unsigned long hp_size = huge_page_size(h);
|
||||
|
||||
switch (hp_size) {
|
||||
#ifndef __PAGETABLE_PMD_FOLDED
|
||||
case PUD_SIZE:
|
||||
return P4D_SIZE - PUD_SIZE;
|
||||
#endif
|
||||
case PMD_SIZE:
|
||||
return PUD_SIZE - PMD_SIZE;
|
||||
case napot_cont_size(NAPOT_CONT64KB_ORDER):
|
||||
return PMD_SIZE - napot_cont_size(NAPOT_CONT64KB_ORDER);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
static pte_t get_clear_contig(struct mm_struct *mm,
|
||||
unsigned long addr,
|
||||
pte_t *ptep,
|
||||
@@ -177,13 +197,36 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags)
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void clear_flush(struct mm_struct *mm,
|
||||
unsigned long addr,
|
||||
pte_t *ptep,
|
||||
unsigned long pgsize,
|
||||
unsigned long ncontig)
|
||||
{
|
||||
struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0);
|
||||
unsigned long i, saddr = addr;
|
||||
|
||||
for (i = 0; i < ncontig; i++, addr += pgsize, ptep++)
|
||||
ptep_get_and_clear(mm, addr, ptep);
|
||||
|
||||
flush_tlb_range(&vma, saddr, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* When dealing with NAPOT mappings, the privileged specification indicates that
|
||||
* "if an update needs to be made, the OS generally should first mark all of the
|
||||
* PTEs invalid, then issue SFENCE.VMA instruction(s) covering all 4 KiB regions
|
||||
* within the range, [...] then update the PTE(s), as described in Section
|
||||
* 4.2.1.". That's the equivalent of the Break-Before-Make approach used by
|
||||
* arm64.
|
||||
*/
|
||||
void set_huge_pte_at(struct mm_struct *mm,
|
||||
unsigned long addr,
|
||||
pte_t *ptep,
|
||||
pte_t pte,
|
||||
unsigned long sz)
|
||||
{
|
||||
unsigned long hugepage_shift;
|
||||
unsigned long hugepage_shift, pgsize;
|
||||
int i, pte_num;
|
||||
|
||||
if (sz >= PGDIR_SIZE)
|
||||
@@ -198,7 +241,22 @@ void set_huge_pte_at(struct mm_struct *mm,
|
||||
hugepage_shift = PAGE_SHIFT;
|
||||
|
||||
pte_num = sz >> hugepage_shift;
|
||||
for (i = 0; i < pte_num; i++, ptep++, addr += (1 << hugepage_shift))
|
||||
pgsize = 1 << hugepage_shift;
|
||||
|
||||
if (!pte_present(pte)) {
|
||||
for (i = 0; i < pte_num; i++, ptep++, addr += pgsize)
|
||||
set_ptes(mm, addr, ptep, pte, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pte_napot(pte)) {
|
||||
set_ptes(mm, addr, ptep, pte, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
clear_flush(mm, addr, ptep, pgsize, pte_num);
|
||||
|
||||
for (i = 0; i < pte_num; i++, ptep++, addr += pgsize)
|
||||
set_pte_at(mm, addr, ptep, pte);
|
||||
}
|
||||
|
||||
@@ -306,7 +364,7 @@ void huge_pte_clear(struct mm_struct *mm,
|
||||
pte_clear(mm, addr, ptep);
|
||||
}
|
||||
|
||||
static __init bool is_napot_size(unsigned long size)
|
||||
static bool is_napot_size(unsigned long size)
|
||||
{
|
||||
unsigned long order;
|
||||
|
||||
@@ -334,7 +392,7 @@ arch_initcall(napot_hugetlbpages_init);
|
||||
|
||||
#else
|
||||
|
||||
static __init bool is_napot_size(unsigned long size)
|
||||
static bool is_napot_size(unsigned long size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -351,7 +409,7 @@ int pmd_huge(pmd_t pmd)
|
||||
return pmd_leaf(pmd);
|
||||
}
|
||||
|
||||
bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||
static bool __hugetlb_valid_size(unsigned long size)
|
||||
{
|
||||
if (size == HPAGE_SIZE)
|
||||
return true;
|
||||
@@ -363,6 +421,16 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool __init arch_hugetlb_valid_size(unsigned long size)
|
||||
{
|
||||
return __hugetlb_valid_size(size);
|
||||
}
|
||||
|
||||
bool arch_hugetlb_migration_supported(struct hstate *h)
|
||||
{
|
||||
return __hugetlb_valid_size(huge_page_size(h));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CONTIG_ALLOC
|
||||
static __init int gigantic_pages_init(void)
|
||||
{
|
||||
|
||||
@@ -1502,6 +1502,10 @@ void __init misc_mem_init(void)
|
||||
early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT);
|
||||
arch_numa_init();
|
||||
sparse_init();
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
/* The entire VMEMMAP region has been populated. Flush TLB for this region */
|
||||
local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END);
|
||||
#endif
|
||||
zone_sizes_init();
|
||||
reserve_crashkernel();
|
||||
memblock_dump_all();
|
||||
|
||||
@@ -8,28 +8,50 @@
|
||||
|
||||
static inline void local_flush_tlb_all_asid(unsigned long asid)
|
||||
{
|
||||
__asm__ __volatile__ ("sfence.vma x0, %0"
|
||||
:
|
||||
: "r" (asid)
|
||||
: "memory");
|
||||
if (asid != FLUSH_TLB_NO_ASID)
|
||||
__asm__ __volatile__ ("sfence.vma x0, %0"
|
||||
:
|
||||
: "r" (asid)
|
||||
: "memory");
|
||||
else
|
||||
local_flush_tlb_all();
|
||||
}
|
||||
|
||||
static inline void local_flush_tlb_page_asid(unsigned long addr,
|
||||
unsigned long asid)
|
||||
{
|
||||
__asm__ __volatile__ ("sfence.vma %0, %1"
|
||||
:
|
||||
: "r" (addr), "r" (asid)
|
||||
: "memory");
|
||||
if (asid != FLUSH_TLB_NO_ASID)
|
||||
__asm__ __volatile__ ("sfence.vma %0, %1"
|
||||
:
|
||||
: "r" (addr), "r" (asid)
|
||||
: "memory");
|
||||
else
|
||||
local_flush_tlb_page(addr);
|
||||
}
|
||||
|
||||
static inline void local_flush_tlb_range(unsigned long start,
|
||||
unsigned long size, unsigned long stride)
|
||||
/*
|
||||
* Flush entire TLB if number of entries to be flushed is greater
|
||||
* than the threshold below.
|
||||
*/
|
||||
static unsigned long tlb_flush_all_threshold __read_mostly = 64;
|
||||
|
||||
static void local_flush_tlb_range_threshold_asid(unsigned long start,
|
||||
unsigned long size,
|
||||
unsigned long stride,
|
||||
unsigned long asid)
|
||||
{
|
||||
if (size <= stride)
|
||||
local_flush_tlb_page(start);
|
||||
else
|
||||
local_flush_tlb_all();
|
||||
unsigned long nr_ptes_in_range = DIV_ROUND_UP(size, stride);
|
||||
int i;
|
||||
|
||||
if (nr_ptes_in_range > tlb_flush_all_threshold) {
|
||||
local_flush_tlb_all_asid(asid);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_ptes_in_range; ++i) {
|
||||
local_flush_tlb_page_asid(start, asid);
|
||||
start += stride;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void local_flush_tlb_range_asid(unsigned long start,
|
||||
@@ -37,8 +59,16 @@ static inline void local_flush_tlb_range_asid(unsigned long start,
|
||||
{
|
||||
if (size <= stride)
|
||||
local_flush_tlb_page_asid(start, asid);
|
||||
else
|
||||
else if (size == FLUSH_TLB_MAX_SIZE)
|
||||
local_flush_tlb_all_asid(asid);
|
||||
else
|
||||
local_flush_tlb_range_threshold_asid(start, size, stride, asid);
|
||||
}
|
||||
|
||||
/* Flush a range of kernel pages without broadcasting */
|
||||
void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
local_flush_tlb_range_asid(start, end - start, PAGE_SIZE, FLUSH_TLB_NO_ASID);
|
||||
}
|
||||
|
||||
static void __ipi_flush_tlb_all(void *info)
|
||||
@@ -51,7 +81,7 @@ void flush_tlb_all(void)
|
||||
if (riscv_use_ipi_for_rfence())
|
||||
on_each_cpu(__ipi_flush_tlb_all, NULL, 1);
|
||||
else
|
||||
sbi_remote_sfence_vma(NULL, 0, -1);
|
||||
sbi_remote_sfence_vma_asid(NULL, 0, FLUSH_TLB_MAX_SIZE, FLUSH_TLB_NO_ASID);
|
||||
}
|
||||
|
||||
struct flush_tlb_range_data {
|
||||
@@ -68,68 +98,62 @@ static void __ipi_flush_tlb_range_asid(void *info)
|
||||
local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
|
||||
}
|
||||
|
||||
static void __ipi_flush_tlb_range(void *info)
|
||||
{
|
||||
struct flush_tlb_range_data *d = info;
|
||||
|
||||
local_flush_tlb_range(d->start, d->size, d->stride);
|
||||
}
|
||||
|
||||
static void __flush_tlb_range(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long size, unsigned long stride)
|
||||
{
|
||||
struct flush_tlb_range_data ftd;
|
||||
struct cpumask *cmask = mm_cpumask(mm);
|
||||
unsigned int cpuid;
|
||||
const struct cpumask *cmask;
|
||||
unsigned long asid = FLUSH_TLB_NO_ASID;
|
||||
bool broadcast;
|
||||
|
||||
if (cpumask_empty(cmask))
|
||||
return;
|
||||
if (mm) {
|
||||
unsigned int cpuid;
|
||||
|
||||
cpuid = get_cpu();
|
||||
/* check if the tlbflush needs to be sent to other CPUs */
|
||||
broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
|
||||
if (static_branch_unlikely(&use_asid_allocator)) {
|
||||
unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask;
|
||||
cmask = mm_cpumask(mm);
|
||||
if (cpumask_empty(cmask))
|
||||
return;
|
||||
|
||||
if (broadcast) {
|
||||
if (riscv_use_ipi_for_rfence()) {
|
||||
ftd.asid = asid;
|
||||
ftd.start = start;
|
||||
ftd.size = size;
|
||||
ftd.stride = stride;
|
||||
on_each_cpu_mask(cmask,
|
||||
__ipi_flush_tlb_range_asid,
|
||||
&ftd, 1);
|
||||
} else
|
||||
sbi_remote_sfence_vma_asid(cmask,
|
||||
start, size, asid);
|
||||
} else {
|
||||
local_flush_tlb_range_asid(start, size, stride, asid);
|
||||
}
|
||||
cpuid = get_cpu();
|
||||
/* check if the tlbflush needs to be sent to other CPUs */
|
||||
broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
|
||||
|
||||
if (static_branch_unlikely(&use_asid_allocator))
|
||||
asid = atomic_long_read(&mm->context.id) & asid_mask;
|
||||
} else {
|
||||
if (broadcast) {
|
||||
if (riscv_use_ipi_for_rfence()) {
|
||||
ftd.asid = 0;
|
||||
ftd.start = start;
|
||||
ftd.size = size;
|
||||
ftd.stride = stride;
|
||||
on_each_cpu_mask(cmask,
|
||||
__ipi_flush_tlb_range,
|
||||
&ftd, 1);
|
||||
} else
|
||||
sbi_remote_sfence_vma(cmask, start, size);
|
||||
} else {
|
||||
local_flush_tlb_range(start, size, stride);
|
||||
}
|
||||
cmask = cpu_online_mask;
|
||||
broadcast = true;
|
||||
}
|
||||
|
||||
put_cpu();
|
||||
if (broadcast) {
|
||||
if (riscv_use_ipi_for_rfence()) {
|
||||
ftd.asid = asid;
|
||||
ftd.start = start;
|
||||
ftd.size = size;
|
||||
ftd.stride = stride;
|
||||
on_each_cpu_mask(cmask,
|
||||
__ipi_flush_tlb_range_asid,
|
||||
&ftd, 1);
|
||||
} else
|
||||
sbi_remote_sfence_vma_asid(cmask,
|
||||
start, size, asid);
|
||||
} else {
|
||||
local_flush_tlb_range_asid(start, size, stride, asid);
|
||||
}
|
||||
|
||||
if (mm)
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
void flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
__flush_tlb_range(mm, 0, -1, PAGE_SIZE);
|
||||
__flush_tlb_range(mm, 0, FLUSH_TLB_MAX_SIZE, PAGE_SIZE);
|
||||
}
|
||||
|
||||
void flush_tlb_mm_range(struct mm_struct *mm,
|
||||
unsigned long start, unsigned long end,
|
||||
unsigned int page_size)
|
||||
{
|
||||
__flush_tlb_range(mm, start, end - start, page_size);
|
||||
}
|
||||
|
||||
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
|
||||
@@ -142,6 +166,12 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
{
|
||||
__flush_tlb_range(vma->vm_mm, start, end - start, PAGE_SIZE);
|
||||
}
|
||||
|
||||
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
__flush_tlb_range(NULL, start, end - start, PAGE_SIZE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end)
|
||||
|
||||
@@ -90,6 +90,7 @@ extern void copy_from_user_page(struct vm_area_struct *vma,
|
||||
unsigned long len);
|
||||
|
||||
#define flush_cache_vmap(start, end) local_flush_cache_all(NULL)
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) local_flush_cache_all(NULL)
|
||||
|
||||
#define flush_dcache_mmap_lock(mapping) do { } while (0)
|
||||
|
||||
@@ -48,6 +48,7 @@ static inline void flush_dcache_page(struct page *page)
|
||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||
|
||||
#define flush_cache_vmap(start, end) flush_cache_all()
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) flush_cache_all()
|
||||
|
||||
/* When a context switch happens we must flush all user windows so that
|
||||
|
||||
@@ -75,6 +75,7 @@ void flush_ptrace_access(struct vm_area_struct *, struct page *,
|
||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||
|
||||
#define flush_cache_vmap(start, end) do { } while (0)
|
||||
#define flush_cache_vmap_early(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) do { } while (0)
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
@@ -163,23 +163,23 @@ SYM_CODE_END(__get_user_8_handle_exception)
|
||||
#endif
|
||||
|
||||
/* get_user */
|
||||
_ASM_EXTABLE(1b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE(2b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE(3b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(1b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(2b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(3b, __get_user_handle_exception)
|
||||
#ifdef CONFIG_X86_64
|
||||
_ASM_EXTABLE(4b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(4b, __get_user_handle_exception)
|
||||
#else
|
||||
_ASM_EXTABLE(4b, __get_user_8_handle_exception)
|
||||
_ASM_EXTABLE(5b, __get_user_8_handle_exception)
|
||||
_ASM_EXTABLE_UA(4b, __get_user_8_handle_exception)
|
||||
_ASM_EXTABLE_UA(5b, __get_user_8_handle_exception)
|
||||
#endif
|
||||
|
||||
/* __get_user */
|
||||
_ASM_EXTABLE(6b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE(7b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE(8b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(6b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(7b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(8b, __get_user_handle_exception)
|
||||
#ifdef CONFIG_X86_64
|
||||
_ASM_EXTABLE(9b, __get_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(9b, __get_user_handle_exception)
|
||||
#else
|
||||
_ASM_EXTABLE(9b, __get_user_8_handle_exception)
|
||||
_ASM_EXTABLE(10b, __get_user_8_handle_exception)
|
||||
_ASM_EXTABLE_UA(9b, __get_user_8_handle_exception)
|
||||
_ASM_EXTABLE_UA(10b, __get_user_8_handle_exception)
|
||||
#endif
|
||||
|
||||
@@ -134,15 +134,15 @@ SYM_CODE_START_LOCAL(__put_user_handle_exception)
|
||||
RET
|
||||
SYM_CODE_END(__put_user_handle_exception)
|
||||
|
||||
_ASM_EXTABLE(1b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE(2b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE(3b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE(4b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE(5b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE(6b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE(7b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE(9b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(1b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(2b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(3b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(4b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(5b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(6b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(7b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(9b, __put_user_handle_exception)
|
||||
#ifdef CONFIG_X86_32
|
||||
_ASM_EXTABLE(8b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE(10b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(8b, __put_user_handle_exception)
|
||||
_ASM_EXTABLE_UA(10b, __put_user_handle_exception)
|
||||
#endif
|
||||
|
||||
@@ -116,8 +116,9 @@ void flush_cache_page(struct vm_area_struct*,
|
||||
#define flush_cache_mm(mm) flush_cache_all()
|
||||
#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
|
||||
|
||||
#define flush_cache_vmap(start,end) flush_cache_all()
|
||||
#define flush_cache_vunmap(start,end) flush_cache_all()
|
||||
#define flush_cache_vmap(start,end) flush_cache_all()
|
||||
#define flush_cache_vmap_early(start,end) do { } while (0)
|
||||
#define flush_cache_vunmap(start,end) flush_cache_all()
|
||||
|
||||
void flush_dcache_folio(struct folio *folio);
|
||||
#define flush_dcache_folio flush_dcache_folio
|
||||
@@ -140,6 +141,7 @@ void local_flush_cache_page(struct vm_area_struct *vma,
|
||||
#define flush_cache_dup_mm(mm) do { } while (0)
|
||||
|
||||
#define flush_cache_vmap(start,end) do { } while (0)
|
||||
#define flush_cache_vmap_early(start,end) do { } while (0)
|
||||
#define flush_cache_vunmap(start,end) do { } while (0)
|
||||
|
||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
|
||||
|
||||
@@ -1353,6 +1353,13 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now)
|
||||
|
||||
lockdep_assert_held(&iocg->waitq.lock);
|
||||
|
||||
/*
|
||||
* If the delay is set by another CPU, we may be in the past. No need to
|
||||
* change anything if so. This avoids decay calculation underflow.
|
||||
*/
|
||||
if (time_before64(now->now, iocg->delay_at))
|
||||
return false;
|
||||
|
||||
/* calculate the current delay in effect - 1/2 every second */
|
||||
tdelta = now->now - iocg->delay_at;
|
||||
if (iocg->delay)
|
||||
|
||||
@@ -2930,6 +2930,8 @@ open_card_ubr0(struct idt77252_dev *card)
|
||||
vc->scq = alloc_scq(card, vc->class);
|
||||
if (!vc->scq) {
|
||||
printk("%s: can't get SCQ.\n", card->name);
|
||||
kfree(card->vcs[0]);
|
||||
card->vcs[0] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,15 +38,17 @@ static int dpaa2_qdma_alloc_chan_resources(struct dma_chan *chan)
|
||||
if (!dpaa2_chan->fd_pool)
|
||||
goto err;
|
||||
|
||||
dpaa2_chan->fl_pool = dma_pool_create("fl_pool", dev,
|
||||
sizeof(struct dpaa2_fl_entry),
|
||||
sizeof(struct dpaa2_fl_entry), 0);
|
||||
dpaa2_chan->fl_pool =
|
||||
dma_pool_create("fl_pool", dev,
|
||||
sizeof(struct dpaa2_fl_entry) * 3,
|
||||
sizeof(struct dpaa2_fl_entry), 0);
|
||||
|
||||
if (!dpaa2_chan->fl_pool)
|
||||
goto err_fd;
|
||||
|
||||
dpaa2_chan->sdd_pool =
|
||||
dma_pool_create("sdd_pool", dev,
|
||||
sizeof(struct dpaa2_qdma_sd_d),
|
||||
sizeof(struct dpaa2_qdma_sd_d) * 2,
|
||||
sizeof(struct dpaa2_qdma_sd_d), 0);
|
||||
if (!dpaa2_chan->sdd_pool)
|
||||
goto err_fl;
|
||||
|
||||
@@ -514,11 +514,11 @@ static struct fsl_qdma_queue
|
||||
queue_temp = queue_head + i + (j * queue_num);
|
||||
|
||||
queue_temp->cq =
|
||||
dma_alloc_coherent(&pdev->dev,
|
||||
sizeof(struct fsl_qdma_format) *
|
||||
queue_size[i],
|
||||
&queue_temp->bus_addr,
|
||||
GFP_KERNEL);
|
||||
dmam_alloc_coherent(&pdev->dev,
|
||||
sizeof(struct fsl_qdma_format) *
|
||||
queue_size[i],
|
||||
&queue_temp->bus_addr,
|
||||
GFP_KERNEL);
|
||||
if (!queue_temp->cq)
|
||||
return NULL;
|
||||
queue_temp->block_base = fsl_qdma->block_base +
|
||||
@@ -563,11 +563,11 @@ static struct fsl_qdma_queue
|
||||
/*
|
||||
* Buffer for queue command
|
||||
*/
|
||||
status_head->cq = dma_alloc_coherent(&pdev->dev,
|
||||
sizeof(struct fsl_qdma_format) *
|
||||
status_size,
|
||||
&status_head->bus_addr,
|
||||
GFP_KERNEL);
|
||||
status_head->cq = dmam_alloc_coherent(&pdev->dev,
|
||||
sizeof(struct fsl_qdma_format) *
|
||||
status_size,
|
||||
&status_head->bus_addr,
|
||||
GFP_KERNEL);
|
||||
if (!status_head->cq) {
|
||||
devm_kfree(&pdev->dev, status_head);
|
||||
return NULL;
|
||||
@@ -1268,8 +1268,6 @@ static void fsl_qdma_cleanup_vchan(struct dma_device *dmadev)
|
||||
|
||||
static int fsl_qdma_remove(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
struct fsl_qdma_queue *status;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct fsl_qdma_engine *fsl_qdma = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -1278,11 +1276,6 @@ static int fsl_qdma_remove(struct platform_device *pdev)
|
||||
of_dma_controller_free(np);
|
||||
dma_async_device_unregister(&fsl_qdma->dma_dev);
|
||||
|
||||
for (i = 0; i < fsl_qdma->block_number; i++) {
|
||||
status = fsl_qdma->status[i];
|
||||
dma_free_coherent(&pdev->dev, sizeof(struct fsl_qdma_format) *
|
||||
status->n_cq, status->cq, status->bus_addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -3968,6 +3968,7 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc,
|
||||
{
|
||||
struct udma_chan *uc = to_udma_chan(&vc->chan);
|
||||
struct udma_desc *d;
|
||||
u8 status;
|
||||
|
||||
if (!vd)
|
||||
return;
|
||||
@@ -3977,12 +3978,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc,
|
||||
if (d->metadata_size)
|
||||
udma_fetch_epib(uc, d);
|
||||
|
||||
/* Provide residue information for the client */
|
||||
if (result) {
|
||||
void *desc_vaddr = udma_curr_cppi5_desc_vaddr(d, d->desc_idx);
|
||||
|
||||
if (cppi5_desc_get_type(desc_vaddr) ==
|
||||
CPPI5_INFO0_DESC_TYPE_VAL_HOST) {
|
||||
/* Provide residue information for the client */
|
||||
result->residue = d->residue -
|
||||
cppi5_hdesc_get_pktlen(desc_vaddr);
|
||||
if (result->residue)
|
||||
@@ -3991,7 +3992,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc,
|
||||
result->result = DMA_TRANS_NOERROR;
|
||||
} else {
|
||||
result->residue = 0;
|
||||
result->result = DMA_TRANS_NOERROR;
|
||||
/* Propagate TR Response errors to the client */
|
||||
status = d->hwdesc[0].tr_resp_base->status;
|
||||
if (status)
|
||||
result->result = DMA_TRANS_ABORTED;
|
||||
else
|
||||
result->result = DMA_TRANS_NOERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -956,7 +956,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
|
||||
|
||||
efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long random_seed,
|
||||
int memory_type, unsigned long alloc_limit);
|
||||
int memory_type, unsigned long alloc_min,
|
||||
unsigned long alloc_max);
|
||||
|
||||
efi_status_t efi_random_get_seed(void);
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ efi_status_t efi_kaslr_relocate_kernel(unsigned long *image_addr,
|
||||
*/
|
||||
status = efi_random_alloc(*reserve_size, min_kimg_align,
|
||||
reserve_addr, phys_seed,
|
||||
EFI_LOADER_CODE, EFI_ALLOC_LIMIT);
|
||||
EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
|
||||
} else {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
|
||||
unsigned long size,
|
||||
unsigned long align_shift,
|
||||
u64 alloc_limit)
|
||||
u64 alloc_min, u64 alloc_max)
|
||||
{
|
||||
unsigned long align = 1UL << align_shift;
|
||||
u64 first_slot, last_slot, region_end;
|
||||
@@ -30,11 +30,11 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
|
||||
return 0;
|
||||
|
||||
region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
|
||||
alloc_limit);
|
||||
alloc_max);
|
||||
if (region_end < size)
|
||||
return 0;
|
||||
|
||||
first_slot = round_up(md->phys_addr, align);
|
||||
first_slot = round_up(max(md->phys_addr, alloc_min), align);
|
||||
last_slot = round_down(region_end - size + 1, align);
|
||||
|
||||
if (first_slot > last_slot)
|
||||
@@ -56,7 +56,8 @@ efi_status_t efi_random_alloc(unsigned long size,
|
||||
unsigned long *addr,
|
||||
unsigned long random_seed,
|
||||
int memory_type,
|
||||
unsigned long alloc_limit)
|
||||
unsigned long alloc_min,
|
||||
unsigned long alloc_max)
|
||||
{
|
||||
unsigned long total_slots = 0, target_slot;
|
||||
unsigned long total_mirrored_slots = 0;
|
||||
@@ -78,7 +79,8 @@ efi_status_t efi_random_alloc(unsigned long size,
|
||||
efi_memory_desc_t *md = (void *)map->map + map_offset;
|
||||
unsigned long slots;
|
||||
|
||||
slots = get_entry_num_slots(md, size, ilog2(align), alloc_limit);
|
||||
slots = get_entry_num_slots(md, size, ilog2(align), alloc_min,
|
||||
alloc_max);
|
||||
MD_NUM_SLOTS(md) = slots;
|
||||
total_slots += slots;
|
||||
if (md->attribute & EFI_MEMORY_MORE_RELIABLE)
|
||||
|
||||
@@ -223,8 +223,8 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
|
||||
}
|
||||
}
|
||||
|
||||
void efi_adjust_memory_range_protection(unsigned long start,
|
||||
unsigned long size)
|
||||
efi_status_t efi_adjust_memory_range_protection(unsigned long start,
|
||||
unsigned long size)
|
||||
{
|
||||
efi_status_t status;
|
||||
efi_gcd_memory_space_desc_t desc;
|
||||
@@ -236,13 +236,17 @@ void efi_adjust_memory_range_protection(unsigned long start,
|
||||
rounded_end = roundup(start + size, EFI_PAGE_SIZE);
|
||||
|
||||
if (memattr != NULL) {
|
||||
efi_call_proto(memattr, clear_memory_attributes, rounded_start,
|
||||
rounded_end - rounded_start, EFI_MEMORY_XP);
|
||||
return;
|
||||
status = efi_call_proto(memattr, clear_memory_attributes,
|
||||
rounded_start,
|
||||
rounded_end - rounded_start,
|
||||
EFI_MEMORY_XP);
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_warn("Failed to clear EFI_MEMORY_XP attribute\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (efi_dxe_table == NULL)
|
||||
return;
|
||||
return EFI_SUCCESS;
|
||||
|
||||
/*
|
||||
* Don't modify memory region attributes, they are
|
||||
@@ -255,7 +259,7 @@ void efi_adjust_memory_range_protection(unsigned long start,
|
||||
status = efi_dxe_call(get_memory_space_descriptor, start, &desc);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
return;
|
||||
break;
|
||||
|
||||
next = desc.base_address + desc.length;
|
||||
|
||||
@@ -280,8 +284,10 @@ void efi_adjust_memory_range_protection(unsigned long start,
|
||||
unprotect_start,
|
||||
unprotect_start + unprotect_size,
|
||||
status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static void setup_unaccepted_memory(void)
|
||||
@@ -825,6 +831,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
|
||||
|
||||
status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
|
||||
seed[0], EFI_LOADER_CODE,
|
||||
LOAD_PHYSICAL_ADDR,
|
||||
EFI_X86_KERNEL_ALLOC_LIMIT);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
@@ -837,9 +844,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
|
||||
|
||||
*kernel_entry = addr + entry;
|
||||
|
||||
efi_adjust_memory_range_protection(addr, kernel_total_size);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return efi_adjust_memory_range_protection(addr, kernel_total_size);
|
||||
}
|
||||
|
||||
static void __noreturn enter_kernel(unsigned long kernel_addr,
|
||||
|
||||
@@ -7,8 +7,8 @@ extern struct boot_params *boot_params_pointer asm("boot_params");
|
||||
extern void trampoline_32bit_src(void *, bool);
|
||||
extern const u16 trampoline_ljmp_imm_offset;
|
||||
|
||||
void efi_adjust_memory_range_protection(unsigned long start,
|
||||
unsigned long size);
|
||||
efi_status_t efi_adjust_memory_range_protection(unsigned long start,
|
||||
unsigned long size);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
efi_status_t efi_setup_5level_paging(void);
|
||||
|
||||
@@ -119,7 +119,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
|
||||
}
|
||||
|
||||
status = efi_random_alloc(alloc_size, min_kimg_align, &image_base,
|
||||
seed, EFI_LOADER_CODE, EFI_ALLOC_LIMIT);
|
||||
seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate memory\n");
|
||||
goto free_cmdline;
|
||||
|
||||
@@ -206,28 +206,32 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
|
||||
void dcn21_set_pipe(struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct abm *abm = pipe_ctx->stream_res.abm;
|
||||
uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
|
||||
struct timing_generator *tg = pipe_ctx->stream_res.tg;
|
||||
struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
|
||||
struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu;
|
||||
uint32_t otg_inst;
|
||||
|
||||
if (!abm && !tg && !panel_cntl)
|
||||
return;
|
||||
|
||||
otg_inst = tg->inst;
|
||||
|
||||
if (dmcu) {
|
||||
dce110_set_pipe(pipe_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (abm && panel_cntl) {
|
||||
if (abm->funcs && abm->funcs->set_pipe_ex) {
|
||||
abm->funcs->set_pipe_ex(abm,
|
||||
if (abm->funcs && abm->funcs->set_pipe_ex) {
|
||||
abm->funcs->set_pipe_ex(abm,
|
||||
otg_inst,
|
||||
SET_ABM_PIPE_NORMAL,
|
||||
panel_cntl->inst,
|
||||
panel_cntl->pwrseq_inst);
|
||||
} else {
|
||||
dmub_abm_set_pipe(abm, otg_inst,
|
||||
SET_ABM_PIPE_NORMAL,
|
||||
panel_cntl->inst,
|
||||
panel_cntl->pwrseq_inst);
|
||||
}
|
||||
} else {
|
||||
dmub_abm_set_pipe(abm, otg_inst,
|
||||
SET_ABM_PIPE_NORMAL,
|
||||
panel_cntl->inst,
|
||||
panel_cntl->pwrseq_inst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,34 +241,35 @@ bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx,
|
||||
{
|
||||
struct dc_context *dc = pipe_ctx->stream->ctx;
|
||||
struct abm *abm = pipe_ctx->stream_res.abm;
|
||||
struct timing_generator *tg = pipe_ctx->stream_res.tg;
|
||||
struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
|
||||
uint32_t otg_inst;
|
||||
|
||||
if (!abm && !tg && !panel_cntl)
|
||||
return false;
|
||||
|
||||
otg_inst = tg->inst;
|
||||
|
||||
if (dc->dc->res_pool->dmcu) {
|
||||
dce110_set_backlight_level(pipe_ctx, backlight_pwm_u16_16, frame_ramp);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (abm != NULL) {
|
||||
uint32_t otg_inst = pipe_ctx->stream_res.tg->inst;
|
||||
|
||||
if (abm && panel_cntl) {
|
||||
if (abm->funcs && abm->funcs->set_pipe_ex) {
|
||||
abm->funcs->set_pipe_ex(abm,
|
||||
otg_inst,
|
||||
SET_ABM_PIPE_NORMAL,
|
||||
panel_cntl->inst,
|
||||
panel_cntl->pwrseq_inst);
|
||||
} else {
|
||||
dmub_abm_set_pipe(abm,
|
||||
otg_inst,
|
||||
SET_ABM_PIPE_NORMAL,
|
||||
panel_cntl->inst,
|
||||
panel_cntl->pwrseq_inst);
|
||||
}
|
||||
}
|
||||
if (abm->funcs && abm->funcs->set_pipe_ex) {
|
||||
abm->funcs->set_pipe_ex(abm,
|
||||
otg_inst,
|
||||
SET_ABM_PIPE_NORMAL,
|
||||
panel_cntl->inst,
|
||||
panel_cntl->pwrseq_inst);
|
||||
} else {
|
||||
dmub_abm_set_pipe(abm,
|
||||
otg_inst,
|
||||
SET_ABM_PIPE_NORMAL,
|
||||
panel_cntl->inst,
|
||||
panel_cntl->pwrseq_inst);
|
||||
}
|
||||
|
||||
if (abm && abm->funcs && abm->funcs->set_backlight_level_pwm)
|
||||
if (abm->funcs && abm->funcs->set_backlight_level_pwm)
|
||||
abm->funcs->set_backlight_level_pwm(abm, backlight_pwm_u16_16,
|
||||
frame_ramp, 0, panel_cntl->inst);
|
||||
else
|
||||
|
||||
@@ -996,7 +996,7 @@ static struct stream_encoder *dcn301_stream_encoder_create(enum engine_id eng_id
|
||||
vpg = dcn301_vpg_create(ctx, vpg_inst);
|
||||
afmt = dcn301_afmt_create(ctx, afmt_inst);
|
||||
|
||||
if (!enc1 || !vpg || !afmt) {
|
||||
if (!enc1 || !vpg || !afmt || eng_id >= ARRAY_SIZE(stream_enc_regs)) {
|
||||
kfree(enc1);
|
||||
kfree(vpg);
|
||||
kfree(afmt);
|
||||
|
||||
@@ -2850,8 +2850,7 @@ static int handle_mmio(struct intel_gvt_mmio_table_iter *iter, u32 offset,
|
||||
for (i = start; i < end; i += 4) {
|
||||
p = intel_gvt_find_mmio_info(gvt, i);
|
||||
if (p) {
|
||||
WARN(1, "dup mmio definition offset %x\n",
|
||||
info->offset);
|
||||
WARN(1, "dup mmio definition offset %x\n", i);
|
||||
|
||||
/* We return -EEXIST here to make GVT-g load fail.
|
||||
* So duplicated MMIO can be found as soon as
|
||||
|
||||
@@ -2063,7 +2063,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
|
||||
}
|
||||
|
||||
/* reset the merge 3D HW block */
|
||||
if (phys_enc->hw_pp->merge_3d) {
|
||||
if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) {
|
||||
phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
|
||||
BLEND_3D_NONE);
|
||||
if (phys_enc->hw_ctl->ops.update_pending_flush_merge_3d)
|
||||
@@ -2085,7 +2085,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
|
||||
if (phys_enc->hw_wb)
|
||||
intf_cfg.wb = phys_enc->hw_wb->idx;
|
||||
|
||||
if (phys_enc->hw_pp->merge_3d)
|
||||
if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d)
|
||||
intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx;
|
||||
|
||||
if (ctl->ops.reset_intf_cfg)
|
||||
|
||||
@@ -135,11 +135,6 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
|
||||
tbd = dp_link_get_test_bits_depth(ctrl->link,
|
||||
ctrl->panel->dp_mode.bpp);
|
||||
|
||||
if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) {
|
||||
pr_debug("BIT_DEPTH not set. Configure default\n");
|
||||
tbd = DP_TEST_BIT_DEPTH_8;
|
||||
}
|
||||
|
||||
config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT;
|
||||
|
||||
/* Num of Lanes */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "dp_reg.h"
|
||||
#include "dp_link.h"
|
||||
#include "dp_panel.h"
|
||||
|
||||
@@ -1114,7 +1115,7 @@ int dp_link_process_request(struct dp_link *dp_link)
|
||||
|
||||
int dp_link_get_colorimetry_config(struct dp_link *dp_link)
|
||||
{
|
||||
u32 cc;
|
||||
u32 cc = DP_MISC0_COLORIMERY_CFG_LEGACY_RGB;
|
||||
struct dp_link_private *link;
|
||||
|
||||
if (!dp_link) {
|
||||
@@ -1128,10 +1129,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link)
|
||||
* Unless a video pattern CTS test is ongoing, use RGB_VESA
|
||||
* Only RGB_VESA and RGB_CEA supported for now
|
||||
*/
|
||||
if (dp_link_is_video_pattern_requested(link))
|
||||
cc = link->dp_link.test_video.test_dyn_range;
|
||||
else
|
||||
cc = DP_TEST_DYNAMIC_RANGE_VESA;
|
||||
if (dp_link_is_video_pattern_requested(link)) {
|
||||
if (link->dp_link.test_video.test_dyn_range &
|
||||
DP_TEST_DYNAMIC_RANGE_CEA)
|
||||
cc = DP_MISC0_COLORIMERY_CFG_CEA_RGB;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
@@ -1211,6 +1213,9 @@ void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link)
|
||||
u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
|
||||
{
|
||||
u32 tbd;
|
||||
struct dp_link_private *link;
|
||||
|
||||
link = container_of(dp_link, struct dp_link_private, dp_link);
|
||||
|
||||
/*
|
||||
* Few simplistic rules and assumptions made here:
|
||||
@@ -1228,12 +1233,13 @@ u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
|
||||
tbd = DP_TEST_BIT_DEPTH_10;
|
||||
break;
|
||||
default:
|
||||
tbd = DP_TEST_BIT_DEPTH_UNKNOWN;
|
||||
drm_dbg_dp(link->drm_dev, "bpp=%d not supported, use bpc=8\n",
|
||||
bpp);
|
||||
tbd = DP_TEST_BIT_DEPTH_8;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN)
|
||||
tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT);
|
||||
tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT);
|
||||
|
||||
return tbd;
|
||||
}
|
||||
|
||||
@@ -143,6 +143,9 @@
|
||||
#define DP_MISC0_COLORIMETRY_CFG_SHIFT (0x00000001)
|
||||
#define DP_MISC0_TEST_BITS_DEPTH_SHIFT (0x00000005)
|
||||
|
||||
#define DP_MISC0_COLORIMERY_CFG_LEGACY_RGB (0)
|
||||
#define DP_MISC0_COLORIMERY_CFG_CEA_RGB (0x04)
|
||||
|
||||
#define REG_DP_VALID_BOUNDARY (0x00000030)
|
||||
#define REG_DP_VALID_BOUNDARY_2 (0x00000034)
|
||||
|
||||
|
||||
@@ -193,6 +193,8 @@ struct aspeed_pwm_tacho_data {
|
||||
u8 fan_tach_ch_source[16];
|
||||
struct aspeed_cooling_device *cdev[8];
|
||||
const struct attribute_group *groups[3];
|
||||
/* protects access to shared ASPEED_PTCR_RESULT */
|
||||
struct mutex tach_lock;
|
||||
};
|
||||
|
||||
enum type { TYPEM, TYPEN, TYPEO };
|
||||
@@ -527,6 +529,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
|
||||
u8 fan_tach_ch_source, type, mode, both;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->tach_lock);
|
||||
|
||||
regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
|
||||
regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
|
||||
|
||||
@@ -544,6 +548,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
|
||||
ASPEED_RPM_STATUS_SLEEP_USEC,
|
||||
usec);
|
||||
|
||||
mutex_unlock(&priv->tach_lock);
|
||||
|
||||
/* return -ETIMEDOUT if we didn't get an answer. */
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -903,6 +909,7 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
mutex_init(&priv->tach_lock);
|
||||
priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
|
||||
&aspeed_pwm_tacho_regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
|
||||
@@ -419,7 +419,7 @@ static ssize_t show_temp(struct device *dev,
|
||||
}
|
||||
|
||||
static int create_core_attrs(struct temp_data *tdata, struct device *dev,
|
||||
int attr_no)
|
||||
int index)
|
||||
{
|
||||
int i;
|
||||
static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
|
||||
@@ -431,13 +431,20 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
|
||||
};
|
||||
|
||||
for (i = 0; i < tdata->attr_size; i++) {
|
||||
/*
|
||||
* We map the attr number to core id of the CPU
|
||||
* The attr number is always core id + 2
|
||||
* The Pkgtemp will always show up as temp1_*, if available
|
||||
*/
|
||||
int attr_no = tdata->is_pkg_data ? 1 : tdata->cpu_core_id + 2;
|
||||
|
||||
snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH,
|
||||
"temp%d_%s", attr_no, suffixes[i]);
|
||||
sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
|
||||
tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
|
||||
tdata->sd_attrs[i].dev_attr.attr.mode = 0444;
|
||||
tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
|
||||
tdata->sd_attrs[i].index = attr_no;
|
||||
tdata->sd_attrs[i].index = index;
|
||||
tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr;
|
||||
}
|
||||
tdata->attr_group.attrs = tdata->attrs;
|
||||
@@ -495,30 +502,25 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
|
||||
struct platform_data *pdata = platform_get_drvdata(pdev);
|
||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
||||
u32 eax, edx;
|
||||
int err, index, attr_no;
|
||||
int err, index;
|
||||
|
||||
if (!housekeeping_cpu(cpu, HK_TYPE_MISC))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Find attr number for sysfs:
|
||||
* We map the attr number to core id of the CPU
|
||||
* The attr number is always core id + 2
|
||||
* The Pkgtemp will always show up as temp1_*, if available
|
||||
* Get the index of tdata in pdata->core_data[]
|
||||
* tdata for package: pdata->core_data[1]
|
||||
* tdata for core: pdata->core_data[2] .. pdata->core_data[NUM_REAL_CORES + 1]
|
||||
*/
|
||||
if (pkg_flag) {
|
||||
attr_no = PKG_SYSFS_ATTR_NO;
|
||||
index = PKG_SYSFS_ATTR_NO;
|
||||
} else {
|
||||
index = ida_alloc(&pdata->ida, GFP_KERNEL);
|
||||
index = ida_alloc_max(&pdata->ida, NUM_REAL_CORES - 1, GFP_KERNEL);
|
||||
if (index < 0)
|
||||
return index;
|
||||
pdata->cpu_map[index] = topology_core_id(cpu);
|
||||
attr_no = index + BASE_SYSFS_ATTR_NO;
|
||||
}
|
||||
|
||||
if (attr_no > MAX_CORE_DATA - 1) {
|
||||
err = -ERANGE;
|
||||
goto ida_free;
|
||||
pdata->cpu_map[index] = topology_core_id(cpu);
|
||||
index += BASE_SYSFS_ATTR_NO;
|
||||
}
|
||||
|
||||
tdata = init_temp_data(cpu, pkg_flag);
|
||||
@@ -544,20 +546,20 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
|
||||
if (get_ttarget(tdata, &pdev->dev) >= 0)
|
||||
tdata->attr_size++;
|
||||
|
||||
pdata->core_data[attr_no] = tdata;
|
||||
pdata->core_data[index] = tdata;
|
||||
|
||||
/* Create sysfs interfaces */
|
||||
err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no);
|
||||
err = create_core_attrs(tdata, pdata->hwmon_dev, index);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
|
||||
return 0;
|
||||
exit_free:
|
||||
pdata->core_data[attr_no] = NULL;
|
||||
pdata->core_data[index] = NULL;
|
||||
kfree(tdata);
|
||||
ida_free:
|
||||
if (!pkg_flag)
|
||||
ida_free(&pdata->ida, index);
|
||||
ida_free(&pdata->ida, index - BASE_SYSFS_ATTR_NO);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -811,7 +811,6 @@ static int atkbd_probe(struct atkbd *atkbd)
|
||||
{
|
||||
struct ps2dev *ps2dev = &atkbd->ps2dev;
|
||||
unsigned char param[2];
|
||||
bool skip_getid;
|
||||
|
||||
/*
|
||||
* Some systems, where the bit-twiddling when testing the io-lines of the
|
||||
@@ -825,6 +824,11 @@ static int atkbd_probe(struct atkbd *atkbd)
|
||||
"keyboard reset failed on %s\n",
|
||||
ps2dev->serio->phys);
|
||||
|
||||
if (atkbd_skip_getid(atkbd)) {
|
||||
atkbd->id = 0xab83;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Then we check the keyboard ID. We should get 0xab83 under normal conditions.
|
||||
* Some keyboards report different values, but the first byte is always 0xab or
|
||||
@@ -833,18 +837,17 @@ static int atkbd_probe(struct atkbd *atkbd)
|
||||
*/
|
||||
|
||||
param[0] = param[1] = 0xa5; /* initialize with invalid values */
|
||||
skip_getid = atkbd_skip_getid(atkbd);
|
||||
if (skip_getid || ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
|
||||
if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
|
||||
|
||||
/*
|
||||
* If the get ID command was skipped or failed, we check if we can at least set
|
||||
* If the get ID command failed, we check if we can at least set
|
||||
* the LEDs on the keyboard. This should work on every keyboard out there.
|
||||
* It also turns the LEDs off, which we want anyway.
|
||||
*/
|
||||
param[0] = 0;
|
||||
if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
|
||||
return -1;
|
||||
atkbd->id = skip_getid ? 0xab83 : 0xabba;
|
||||
atkbd->id = 0xabba;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1208,6 +1208,12 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
|
||||
SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP |
|
||||
SERIO_QUIRK_NOPNP)
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NS5x_7xPU"),
|
||||
},
|
||||
.driver_data = (void *)(SERIO_QUIRK_NOAUX)
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"),
|
||||
|
||||
@@ -57,16 +57,16 @@
|
||||
#define SOLO_MP4E_EXT_ADDR(__solo) \
|
||||
(SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))
|
||||
#define SOLO_MP4E_EXT_SIZE(__solo) \
|
||||
max((__solo->nr_chans * 0x00080000), \
|
||||
min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) - \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000))
|
||||
clamp(__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo) - \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo), \
|
||||
__solo->nr_chans * 0x00080000, 0x00ff0000)
|
||||
|
||||
#define __SOLO_JPEG_MIN_SIZE(__solo) (__solo->nr_chans * 0x00080000)
|
||||
#define SOLO_JPEG_EXT_ADDR(__solo) \
|
||||
(SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
|
||||
#define SOLO_JPEG_EXT_SIZE(__solo) \
|
||||
max(__SOLO_JPEG_MIN_SIZE(__solo), \
|
||||
min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000))
|
||||
clamp(__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo), \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo), 0x00ff0000)
|
||||
|
||||
#define SOLO_SDRAM_END(__solo) \
|
||||
(SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
|
||||
|
||||
@@ -993,7 +993,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
|
||||
return 0;
|
||||
|
||||
err_exit_hwts_rx:
|
||||
aq_ring_free(&aq_ptp->hwts_rx);
|
||||
aq_ring_hwts_rx_free(&aq_ptp->hwts_rx);
|
||||
err_exit_ptp_rx:
|
||||
aq_ring_free(&aq_ptp->ptp_rx);
|
||||
err_exit_ptp_tx:
|
||||
@@ -1011,7 +1011,7 @@ void aq_ptp_ring_free(struct aq_nic_s *aq_nic)
|
||||
|
||||
aq_ring_free(&aq_ptp->ptp_tx);
|
||||
aq_ring_free(&aq_ptp->ptp_rx);
|
||||
aq_ring_free(&aq_ptp->hwts_rx);
|
||||
aq_ring_hwts_rx_free(&aq_ptp->hwts_rx);
|
||||
|
||||
aq_ptp_skb_ring_release(&aq_ptp->skb_ring);
|
||||
}
|
||||
|
||||
@@ -919,6 +919,19 @@ void aq_ring_free(struct aq_ring_s *self)
|
||||
}
|
||||
}
|
||||
|
||||
void aq_ring_hwts_rx_free(struct aq_ring_s *self)
|
||||
{
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
if (self->dx_ring) {
|
||||
dma_free_coherent(aq_nic_get_dev(self->aq_nic),
|
||||
self->size * self->dx_size + AQ_CFG_RXDS_DEF,
|
||||
self->dx_ring, self->dx_ring_pa);
|
||||
self->dx_ring = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data)
|
||||
{
|
||||
unsigned int count;
|
||||
|
||||
@@ -210,6 +210,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self);
|
||||
int aq_ring_hwts_rx_alloc(struct aq_ring_s *self,
|
||||
struct aq_nic_s *aq_nic, unsigned int idx,
|
||||
unsigned int size, unsigned int dx_size);
|
||||
void aq_ring_hwts_rx_free(struct aq_ring_s *self);
|
||||
void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic);
|
||||
|
||||
unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data);
|
||||
|
||||
@@ -668,17 +668,25 @@ static void tsnep_xdp_xmit_flush(struct tsnep_tx *tx)
|
||||
|
||||
static bool tsnep_xdp_xmit_back(struct tsnep_adapter *adapter,
|
||||
struct xdp_buff *xdp,
|
||||
struct netdev_queue *tx_nq, struct tsnep_tx *tx)
|
||||
struct netdev_queue *tx_nq, struct tsnep_tx *tx,
|
||||
bool zc)
|
||||
{
|
||||
struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp);
|
||||
bool xmit;
|
||||
u32 type;
|
||||
|
||||
if (unlikely(!xdpf))
|
||||
return false;
|
||||
|
||||
/* no page pool for zero copy */
|
||||
if (zc)
|
||||
type = TSNEP_TX_TYPE_XDP_NDO;
|
||||
else
|
||||
type = TSNEP_TX_TYPE_XDP_TX;
|
||||
|
||||
__netif_tx_lock(tx_nq, smp_processor_id());
|
||||
|
||||
xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, TSNEP_TX_TYPE_XDP_TX);
|
||||
xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, type);
|
||||
|
||||
/* Avoid transmit queue timeout since we share it with the slow path */
|
||||
if (xmit)
|
||||
@@ -1222,7 +1230,7 @@ static bool tsnep_xdp_run_prog(struct tsnep_rx *rx, struct bpf_prog *prog,
|
||||
case XDP_PASS:
|
||||
return false;
|
||||
case XDP_TX:
|
||||
if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx))
|
||||
if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, false))
|
||||
goto out_failure;
|
||||
*status |= TSNEP_XDP_TX;
|
||||
return true;
|
||||
@@ -1272,7 +1280,7 @@ static bool tsnep_xdp_run_prog_zc(struct tsnep_rx *rx, struct bpf_prog *prog,
|
||||
case XDP_PASS:
|
||||
return false;
|
||||
case XDP_TX:
|
||||
if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx))
|
||||
if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, true))
|
||||
goto out_failure;
|
||||
*status |= TSNEP_XDP_TX;
|
||||
return true;
|
||||
|
||||
@@ -951,8 +951,11 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
|
||||
if (pfvf->ptp && qidx < pfvf->hw.tx_queues) {
|
||||
err = qmem_alloc(pfvf->dev, &sq->timestamps, qset->sqe_cnt,
|
||||
sizeof(*sq->timestamps));
|
||||
if (err)
|
||||
if (err) {
|
||||
kfree(sq->sg);
|
||||
sq->sg = NULL;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
sq->head = 0;
|
||||
@@ -968,7 +971,14 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
|
||||
sq->stats.bytes = 0;
|
||||
sq->stats.pkts = 0;
|
||||
|
||||
return pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura);
|
||||
err = pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura);
|
||||
if (err) {
|
||||
kfree(sq->sg);
|
||||
sq->sg = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -216,6 +216,7 @@ struct stmmac_safety_stats {
|
||||
unsigned long mac_errors[32];
|
||||
unsigned long mtl_errors[32];
|
||||
unsigned long dma_errors[32];
|
||||
unsigned long dma_dpp_errors[32];
|
||||
};
|
||||
|
||||
/* Number of fields in Safety Stats */
|
||||
|
||||
@@ -319,6 +319,8 @@
|
||||
#define XGMAC_RXCEIE BIT(4)
|
||||
#define XGMAC_TXCEIE BIT(0)
|
||||
#define XGMAC_MTL_ECC_INT_STATUS 0x000010cc
|
||||
#define XGMAC_MTL_DPP_CONTROL 0x000010e0
|
||||
#define XGMAC_DPP_DISABLE BIT(0)
|
||||
#define XGMAC_MTL_TXQ_OPMODE(x) (0x00001100 + (0x80 * (x)))
|
||||
#define XGMAC_TQS GENMASK(25, 16)
|
||||
#define XGMAC_TQS_SHIFT 16
|
||||
@@ -401,6 +403,7 @@
|
||||
#define XGMAC_DCEIE BIT(1)
|
||||
#define XGMAC_TCEIE BIT(0)
|
||||
#define XGMAC_DMA_ECC_INT_STATUS 0x0000306c
|
||||
#define XGMAC_DMA_DPP_INT_STATUS 0x00003074
|
||||
#define XGMAC_DMA_CH_CONTROL(x) (0x00003100 + (0x80 * (x)))
|
||||
#define XGMAC_SPH BIT(24)
|
||||
#define XGMAC_PBLx8 BIT(16)
|
||||
|
||||
@@ -830,6 +830,44 @@ static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= {
|
||||
{ false, "UNKNOWN", "Unknown Error" }, /* 31 */
|
||||
};
|
||||
|
||||
#define DPP_RX_ERR "Read Rx Descriptor Parity checker Error"
|
||||
#define DPP_TX_ERR "Read Tx Descriptor Parity checker Error"
|
||||
|
||||
static const struct dwxgmac3_error_desc dwxgmac3_dma_dpp_errors[32] = {
|
||||
{ true, "TDPES0", DPP_TX_ERR },
|
||||
{ true, "TDPES1", DPP_TX_ERR },
|
||||
{ true, "TDPES2", DPP_TX_ERR },
|
||||
{ true, "TDPES3", DPP_TX_ERR },
|
||||
{ true, "TDPES4", DPP_TX_ERR },
|
||||
{ true, "TDPES5", DPP_TX_ERR },
|
||||
{ true, "TDPES6", DPP_TX_ERR },
|
||||
{ true, "TDPES7", DPP_TX_ERR },
|
||||
{ true, "TDPES8", DPP_TX_ERR },
|
||||
{ true, "TDPES9", DPP_TX_ERR },
|
||||
{ true, "TDPES10", DPP_TX_ERR },
|
||||
{ true, "TDPES11", DPP_TX_ERR },
|
||||
{ true, "TDPES12", DPP_TX_ERR },
|
||||
{ true, "TDPES13", DPP_TX_ERR },
|
||||
{ true, "TDPES14", DPP_TX_ERR },
|
||||
{ true, "TDPES15", DPP_TX_ERR },
|
||||
{ true, "RDPES0", DPP_RX_ERR },
|
||||
{ true, "RDPES1", DPP_RX_ERR },
|
||||
{ true, "RDPES2", DPP_RX_ERR },
|
||||
{ true, "RDPES3", DPP_RX_ERR },
|
||||
{ true, "RDPES4", DPP_RX_ERR },
|
||||
{ true, "RDPES5", DPP_RX_ERR },
|
||||
{ true, "RDPES6", DPP_RX_ERR },
|
||||
{ true, "RDPES7", DPP_RX_ERR },
|
||||
{ true, "RDPES8", DPP_RX_ERR },
|
||||
{ true, "RDPES9", DPP_RX_ERR },
|
||||
{ true, "RDPES10", DPP_RX_ERR },
|
||||
{ true, "RDPES11", DPP_RX_ERR },
|
||||
{ true, "RDPES12", DPP_RX_ERR },
|
||||
{ true, "RDPES13", DPP_RX_ERR },
|
||||
{ true, "RDPES14", DPP_RX_ERR },
|
||||
{ true, "RDPES15", DPP_RX_ERR },
|
||||
};
|
||||
|
||||
static void dwxgmac3_handle_dma_err(struct net_device *ndev,
|
||||
void __iomem *ioaddr, bool correctable,
|
||||
struct stmmac_safety_stats *stats)
|
||||
@@ -841,6 +879,13 @@ static void dwxgmac3_handle_dma_err(struct net_device *ndev,
|
||||
|
||||
dwxgmac3_log_error(ndev, value, correctable, "DMA",
|
||||
dwxgmac3_dma_errors, STAT_OFF(dma_errors), stats);
|
||||
|
||||
value = readl(ioaddr + XGMAC_DMA_DPP_INT_STATUS);
|
||||
writel(value, ioaddr + XGMAC_DMA_DPP_INT_STATUS);
|
||||
|
||||
dwxgmac3_log_error(ndev, value, false, "DMA_DPP",
|
||||
dwxgmac3_dma_dpp_errors,
|
||||
STAT_OFF(dma_dpp_errors), stats);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -881,6 +926,12 @@ dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp,
|
||||
value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */
|
||||
writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL);
|
||||
|
||||
/* 5. Enable Data Path Parity Protection */
|
||||
value = readl(ioaddr + XGMAC_MTL_DPP_CONTROL);
|
||||
/* already enabled by default, explicit enable it again */
|
||||
value &= ~XGMAC_DPP_DISABLE;
|
||||
writel(value, ioaddr + XGMAC_MTL_DPP_CONTROL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -914,7 +965,11 @@ static int dwxgmac3_safety_feat_irq_status(struct net_device *ndev,
|
||||
ret |= !corr;
|
||||
}
|
||||
|
||||
err = dma & (XGMAC_DEUIS | XGMAC_DECIS);
|
||||
/* DMA_DPP_Interrupt_Status is indicated by MCSIS bit in
|
||||
* DMA_Safety_Interrupt_Status, so we handle DMA Data Path
|
||||
* Parity Errors here
|
||||
*/
|
||||
err = dma & (XGMAC_DEUIS | XGMAC_DECIS | XGMAC_MCSIS);
|
||||
corr = dma & XGMAC_DECIS;
|
||||
if (err) {
|
||||
dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats);
|
||||
@@ -930,6 +985,7 @@ static const struct dwxgmac3_error {
|
||||
{ dwxgmac3_mac_errors },
|
||||
{ dwxgmac3_mtl_errors },
|
||||
{ dwxgmac3_dma_errors },
|
||||
{ dwxgmac3_dma_dpp_errors },
|
||||
};
|
||||
|
||||
static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats,
|
||||
|
||||
@@ -835,14 +835,14 @@ static void nsim_dev_trap_report_work(struct work_struct *work)
|
||||
trap_report_dw.work);
|
||||
nsim_dev = nsim_trap_data->nsim_dev;
|
||||
|
||||
/* For each running port and enabled packet trap, generate a UDP
|
||||
* packet with a random 5-tuple and report it.
|
||||
*/
|
||||
if (!devl_trylock(priv_to_devlink(nsim_dev))) {
|
||||
schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 0);
|
||||
schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For each running port and enabled packet trap, generate a UDP
|
||||
* packet with a random 5-tuple and report it.
|
||||
*/
|
||||
list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) {
|
||||
if (!netif_running(nsim_dev_port->ns->netdev))
|
||||
continue;
|
||||
|
||||
@@ -460,6 +460,10 @@ ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
|
||||
case PPPIOCSMRU:
|
||||
if (get_user(val, p))
|
||||
break;
|
||||
if (val > U16_MAX) {
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (val < PPP_MRU)
|
||||
val = PPP_MRU;
|
||||
ap->mru = val;
|
||||
|
||||
@@ -3780,8 +3780,10 @@ static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
|
||||
if (req->channels[i] == chan)
|
||||
break;
|
||||
}
|
||||
if (i == req->n_channels)
|
||||
req->channels[req->n_channels++] = chan;
|
||||
if (i == req->n_channels) {
|
||||
req->n_channels++;
|
||||
req->channels[i] = chan;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->n_ssids; i++) {
|
||||
if (req->ssids[i].ssid_len == ssid_len &&
|
||||
|
||||
@@ -435,6 +435,9 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
|
||||
mvmvif->ap_ibss_active = false;
|
||||
}
|
||||
|
||||
iwl_mvm_link_changed(mvm, vif, link_conf,
|
||||
LINK_CONTEXT_MODIFY_ACTIVE, false);
|
||||
|
||||
if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) {
|
||||
int ret = iwl_mvm_esr_mode_inactive(mvm, vif);
|
||||
|
||||
@@ -446,9 +449,6 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR)
|
||||
iwl_mvm_mld_rm_snif_sta(mvm, vif);
|
||||
|
||||
iwl_mvm_link_changed(mvm, vif, link_conf,
|
||||
LINK_CONTEXT_MODIFY_ACTIVE, false);
|
||||
|
||||
if (switching_chanctx)
|
||||
return;
|
||||
mvmvif->link[link_id]->phy_ctxt = NULL;
|
||||
|
||||
@@ -673,8 +673,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
|
||||
channel->irq = platform_get_irq_optional(pdev, 0);
|
||||
channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node);
|
||||
if (channel->dr_mode != USB_DR_MODE_UNKNOWN) {
|
||||
int ret;
|
||||
|
||||
channel->is_otg_channel = true;
|
||||
channel->uses_otg_pins = !of_property_read_bool(dev->of_node,
|
||||
"renesas,no-otg-pins");
|
||||
@@ -738,8 +736,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
|
||||
ret = PTR_ERR(provider);
|
||||
goto error;
|
||||
} else if (channel->is_otg_channel) {
|
||||
int ret;
|
||||
|
||||
ret = device_create_file(dev, &dev_attr_role);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
@@ -116,7 +116,7 @@ static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
|
||||
{
|
||||
struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
|
||||
|
||||
if (!phy->comparator)
|
||||
if (!phy->comparator || !phy->comparator->set_vbus)
|
||||
return -ENODEV;
|
||||
|
||||
return phy->comparator->set_vbus(phy->comparator, enabled);
|
||||
@@ -126,7 +126,7 @@ static int omap_usb_start_srp(struct usb_otg *otg)
|
||||
{
|
||||
struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
|
||||
|
||||
if (!phy->comparator)
|
||||
if (!phy->comparator || !phy->comparator->start_srp)
|
||||
return -ENODEV;
|
||||
|
||||
return phy->comparator->start_srp(phy->comparator);
|
||||
|
||||
@@ -282,11 +282,12 @@ static void scsi_eh_inc_host_failed(struct rcu_head *head)
|
||||
{
|
||||
struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
|
||||
struct Scsi_Host *shost = scmd->device->host;
|
||||
unsigned int busy = scsi_host_busy(shost);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
shost->host_failed++;
|
||||
scsi_eh_wakeup(shost, scsi_host_busy(shost));
|
||||
scsi_eh_wakeup(shost, busy);
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -278,9 +278,11 @@ static void scsi_dec_host_busy(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
|
||||
rcu_read_lock();
|
||||
__clear_bit(SCMD_STATE_INFLIGHT, &cmd->state);
|
||||
if (unlikely(scsi_host_in_recovery(shost))) {
|
||||
unsigned int busy = scsi_host_busy(shost);
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (shost->host_failed || shost->host_eh_scheduled)
|
||||
scsi_eh_wakeup(shost, scsi_host_busy(shost));
|
||||
scsi_eh_wakeup(shost, busy);
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
|
||||
#define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f
|
||||
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
|
||||
#define PCI_DEVICE_ID_INTEL_ARLH 0x7ec1
|
||||
#define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e
|
||||
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15
|
||||
#define PCI_DEVICE_ID_AMD_MR 0x163a
|
||||
|
||||
@@ -421,6 +423,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
|
||||
{ PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, ARLH, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) },
|
||||
{ PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) },
|
||||
|
||||
{ PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) },
|
||||
|
||||
@@ -61,7 +61,7 @@ out:
|
||||
|
||||
int dwc3_host_init(struct dwc3 *dwc)
|
||||
{
|
||||
struct property_entry props[4];
|
||||
struct property_entry props[5];
|
||||
struct platform_device *xhci;
|
||||
int ret, irq;
|
||||
int prop_idx = 0;
|
||||
@@ -89,6 +89,8 @@ int dwc3_host_init(struct dwc3 *dwc)
|
||||
|
||||
memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
|
||||
|
||||
props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk");
|
||||
|
||||
if (dwc->usb3_lpm_capable)
|
||||
props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable");
|
||||
|
||||
|
||||
@@ -250,6 +250,9 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
|
||||
if (device_property_read_bool(tmpdev, "quirk-broken-port-ped"))
|
||||
xhci->quirks |= XHCI_BROKEN_PORT_PED;
|
||||
|
||||
if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk"))
|
||||
xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;
|
||||
|
||||
device_property_read_u32(tmpdev, "imod-interval-ns",
|
||||
&xhci->imod_interval);
|
||||
}
|
||||
|
||||
@@ -2377,6 +2377,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
|
||||
/* handle completion code */
|
||||
switch (trb_comp_code) {
|
||||
case COMP_SUCCESS:
|
||||
/* Don't overwrite status if TD had an error, see xHCI 4.9.1 */
|
||||
if (td->error_mid_td)
|
||||
break;
|
||||
if (remaining) {
|
||||
frame->status = short_framestatus;
|
||||
if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
|
||||
@@ -2392,9 +2395,13 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
|
||||
case COMP_BANDWIDTH_OVERRUN_ERROR:
|
||||
frame->status = -ECOMM;
|
||||
break;
|
||||
case COMP_ISOCH_BUFFER_OVERRUN:
|
||||
case COMP_BABBLE_DETECTED_ERROR:
|
||||
sum_trbs_for_length = true;
|
||||
fallthrough;
|
||||
case COMP_ISOCH_BUFFER_OVERRUN:
|
||||
frame->status = -EOVERFLOW;
|
||||
if (ep_trb != td->last_trb)
|
||||
td->error_mid_td = true;
|
||||
break;
|
||||
case COMP_INCOMPATIBLE_DEVICE_ERROR:
|
||||
case COMP_STALL_ERROR:
|
||||
@@ -2402,8 +2409,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
|
||||
break;
|
||||
case COMP_USB_TRANSACTION_ERROR:
|
||||
frame->status = -EPROTO;
|
||||
sum_trbs_for_length = true;
|
||||
if (ep_trb != td->last_trb)
|
||||
return 0;
|
||||
td->error_mid_td = true;
|
||||
break;
|
||||
case COMP_STOPPED:
|
||||
sum_trbs_for_length = true;
|
||||
@@ -2423,6 +2431,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
|
||||
break;
|
||||
}
|
||||
|
||||
if (td->urb_length_set)
|
||||
goto finish_td;
|
||||
|
||||
if (sum_trbs_for_length)
|
||||
frame->actual_length = sum_trb_lengths(xhci, ep->ring, ep_trb) +
|
||||
ep_trb_len - remaining;
|
||||
@@ -2431,6 +2442,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
|
||||
|
||||
td->urb->actual_length += frame->actual_length;
|
||||
|
||||
finish_td:
|
||||
/* Don't give back TD yet if we encountered an error mid TD */
|
||||
if (td->error_mid_td && ep_trb != td->last_trb) {
|
||||
xhci_dbg(xhci, "Error mid isoc TD, wait for final completion event\n");
|
||||
td->urb_length_set = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
|
||||
}
|
||||
|
||||
@@ -2809,17 +2828,51 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
}
|
||||
|
||||
if (!ep_seg) {
|
||||
if (!ep->skip ||
|
||||
!usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
|
||||
/* Some host controllers give a spurious
|
||||
* successful event after a short transfer.
|
||||
* Ignore it.
|
||||
*/
|
||||
if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
|
||||
ep_ring->last_td_was_short) {
|
||||
ep_ring->last_td_was_short = false;
|
||||
goto cleanup;
|
||||
|
||||
if (ep->skip && usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
|
||||
skip_isoc_td(xhci, td, ep, status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some hosts give a spurious success event after a short
|
||||
* transfer. Ignore it.
|
||||
*/
|
||||
if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
|
||||
ep_ring->last_td_was_short) {
|
||||
ep_ring->last_td_was_short = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* xhci 4.10.2 states isoc endpoints should continue
|
||||
* processing the next TD if there was an error mid TD.
|
||||
* So host like NEC don't generate an event for the last
|
||||
* isoc TRB even if the IOC flag is set.
|
||||
* xhci 4.9.1 states that if there are errors in mult-TRB
|
||||
* TDs xHC should generate an error for that TRB, and if xHC
|
||||
* proceeds to the next TD it should genete an event for
|
||||
* any TRB with IOC flag on the way. Other host follow this.
|
||||
* So this event might be for the next TD.
|
||||
*/
|
||||
if (td->error_mid_td &&
|
||||
!list_is_last(&td->td_list, &ep_ring->td_list)) {
|
||||
struct xhci_td *td_next = list_next_entry(td, td_list);
|
||||
|
||||
ep_seg = trb_in_td(xhci, td_next->start_seg, td_next->first_trb,
|
||||
td_next->last_trb, ep_trb_dma, false);
|
||||
if (ep_seg) {
|
||||
/* give back previous TD, start handling new */
|
||||
xhci_dbg(xhci, "Missing TD completion event after mid TD error\n");
|
||||
ep_ring->dequeue = td->last_trb;
|
||||
ep_ring->deq_seg = td->last_trb_seg;
|
||||
inc_deq(xhci, ep_ring);
|
||||
xhci_td_cleanup(xhci, td, ep_ring, td->status);
|
||||
td = td_next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ep_seg) {
|
||||
/* HC is busted, give up! */
|
||||
xhci_err(xhci,
|
||||
"ERROR Transfer event TRB DMA ptr not "
|
||||
@@ -2831,9 +2884,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
ep_trb_dma, true);
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
skip_isoc_td(xhci, td, ep, status);
|
||||
goto cleanup;
|
||||
}
|
||||
if (trb_comp_code == COMP_SHORT_PACKET)
|
||||
ep_ring->last_td_was_short = true;
|
||||
|
||||
@@ -1573,6 +1573,7 @@ struct xhci_td {
|
||||
struct xhci_segment *bounce_seg;
|
||||
/* actual_length of the URB has already been set */
|
||||
bool urb_length_set;
|
||||
bool error_mid_td;
|
||||
unsigned int num_trbs;
|
||||
};
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
|
||||
{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
|
||||
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
|
||||
{ USB_DEVICE(0x10C4, 0x87ED) }, /* IMST USB-Stick for Smart Meter */
|
||||
{ USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */
|
||||
{ USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */
|
||||
{ USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
|
||||
|
||||
@@ -2269,6 +2269,7 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */
|
||||
.driver_info = RSVD(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
|
||||
|
||||
@@ -184,6 +184,8 @@ static const struct usb_device_id id_table[] = {
|
||||
{DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */
|
||||
{DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */
|
||||
{DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */
|
||||
{DEVICE_SWI(0x413c, 0x8217)}, /* Dell Wireless DW5826e */
|
||||
{DEVICE_SWI(0x413c, 0x8218)}, /* Dell Wireless DW5826e QDL */
|
||||
|
||||
/* Huawei devices */
|
||||
{DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
|
||||
|
||||
@@ -4862,8 +4862,7 @@ static void run_state_machine(struct tcpm_port *port)
|
||||
break;
|
||||
case PORT_RESET:
|
||||
tcpm_reset_port(port);
|
||||
tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ?
|
||||
TYPEC_CC_RD : tcpm_rp_cc(port));
|
||||
tcpm_set_cc(port, TYPEC_CC_OPEN);
|
||||
tcpm_set_state(port, PORT_RESET_WAIT_OFF,
|
||||
PD_T_ERROR_RECOVERY);
|
||||
break;
|
||||
|
||||
@@ -1232,6 +1232,24 @@ void ext4_mb_generate_buddy(struct super_block *sb,
|
||||
atomic64_add(period, &sbi->s_mb_generation_time);
|
||||
}
|
||||
|
||||
static void mb_regenerate_buddy(struct ext4_buddy *e4b)
|
||||
{
|
||||
int count;
|
||||
int order = 1;
|
||||
void *buddy;
|
||||
|
||||
while ((buddy = mb_find_buddy(e4b, order++, &count)))
|
||||
mb_set_bits(buddy, 0, count);
|
||||
|
||||
e4b->bd_info->bb_fragments = 0;
|
||||
memset(e4b->bd_info->bb_counters, 0,
|
||||
sizeof(*e4b->bd_info->bb_counters) *
|
||||
(e4b->bd_sb->s_blocksize_bits + 2));
|
||||
|
||||
ext4_mb_generate_buddy(e4b->bd_sb, e4b->bd_buddy,
|
||||
e4b->bd_bitmap, e4b->bd_group, e4b->bd_info);
|
||||
}
|
||||
|
||||
/* The buddy information is attached the buddy cache inode
|
||||
* for convenience. The information regarding each group
|
||||
* is loaded via ext4_mb_load_buddy. The information involve
|
||||
@@ -1920,6 +1938,8 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
|
||||
ext4_mark_group_bitmap_corrupted(
|
||||
sb, e4b->bd_group,
|
||||
EXT4_GROUP_INFO_BBITMAP_CORRUPT);
|
||||
} else {
|
||||
mb_regenerate_buddy(e4b);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -473,7 +473,7 @@ bool al_delete_le(struct ntfs_inode *ni, enum ATTR_TYPE type, CLST vcn,
|
||||
int al_update(struct ntfs_inode *ni, int sync);
|
||||
static inline size_t al_aligned(size_t size)
|
||||
{
|
||||
return (size + 1023) & ~(size_t)1023;
|
||||
return size_add(size, 1023) & ~(size_t)1023;
|
||||
}
|
||||
|
||||
/* Globals from bitfunc.c */
|
||||
|
||||
@@ -263,6 +263,8 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
|
||||
&iface->sockaddr,
|
||||
rc);
|
||||
kref_put(&iface->refcount, release_iface);
|
||||
/* failure to add chan should increase weight */
|
||||
iface->weight_fulfilled++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -410,7 +410,7 @@ skip_sess_setup:
|
||||
rc = SMB3_request_interfaces(xid, tcon, false);
|
||||
free_xid(xid);
|
||||
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
if (rc == -EOPNOTSUPP && ses->chan_count > 1) {
|
||||
/*
|
||||
* some servers like Azure SMB server do not advertise
|
||||
* that multichannel has been disabled with server
|
||||
|
||||
@@ -147,7 +147,7 @@ config XFS_ONLINE_SCRUB_STATS
|
||||
bool "XFS online metadata check usage data collection"
|
||||
default y
|
||||
depends on XFS_ONLINE_SCRUB
|
||||
select XFS_DEBUG
|
||||
select DEBUG_FS
|
||||
help
|
||||
If you say Y here, the kernel will gather usage data about
|
||||
the online metadata check subsystem. This includes the number
|
||||
|
||||
@@ -2275,16 +2275,37 @@ xfs_alloc_min_freelist(
|
||||
|
||||
ASSERT(mp->m_alloc_maxlevels > 0);
|
||||
|
||||
/*
|
||||
* For a btree shorter than the maximum height, the worst case is that
|
||||
* every level gets split and a new level is added, then while inserting
|
||||
* another entry to refill the AGFL, every level under the old root gets
|
||||
* split again. This is:
|
||||
*
|
||||
* (full height split reservation) + (AGFL refill split height)
|
||||
* = (current height + 1) + (current height - 1)
|
||||
* = (new height) + (new height - 2)
|
||||
* = 2 * new height - 2
|
||||
*
|
||||
* For a btree of maximum height, the worst case is that every level
|
||||
* under the root gets split, then while inserting another entry to
|
||||
* refill the AGFL, every level under the root gets split again. This is
|
||||
* also:
|
||||
*
|
||||
* 2 * (current height - 1)
|
||||
* = 2 * (new height - 1)
|
||||
* = 2 * new height - 2
|
||||
*/
|
||||
|
||||
/* space needed by-bno freespace btree */
|
||||
min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1,
|
||||
mp->m_alloc_maxlevels);
|
||||
mp->m_alloc_maxlevels) * 2 - 2;
|
||||
/* space needed by-size freespace btree */
|
||||
min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1,
|
||||
mp->m_alloc_maxlevels);
|
||||
mp->m_alloc_maxlevels) * 2 - 2;
|
||||
/* space needed reverse mapping used space btree */
|
||||
if (xfs_has_rmapbt(mp))
|
||||
min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1,
|
||||
mp->m_rmap_maxlevels);
|
||||
mp->m_rmap_maxlevels) * 2 - 2;
|
||||
|
||||
return min_free;
|
||||
}
|
||||
|
||||
@@ -4827,7 +4827,7 @@ xfs_bmap_del_extent_delay(
|
||||
ASSERT(got_endoff >= del_endoff);
|
||||
|
||||
if (isrt) {
|
||||
uint64_t rtexts = XFS_FSB_TO_B(mp, del->br_blockcount);
|
||||
uint64_t rtexts = del->br_blockcount;
|
||||
|
||||
do_div(rtexts, mp->m_sb.sb_rextsize);
|
||||
xfs_mod_frextents(mp, rtexts);
|
||||
@@ -5057,33 +5057,20 @@ xfs_bmap_del_extent_real(
|
||||
|
||||
flags = XFS_ILOG_CORE;
|
||||
if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
|
||||
xfs_filblks_t len;
|
||||
xfs_extlen_t mod;
|
||||
|
||||
len = div_u64_rem(del->br_blockcount, mp->m_sb.sb_rextsize,
|
||||
&mod);
|
||||
ASSERT(mod == 0);
|
||||
|
||||
if (!(bflags & XFS_BMAPI_REMAP)) {
|
||||
xfs_fsblock_t bno;
|
||||
|
||||
bno = div_u64_rem(del->br_startblock,
|
||||
mp->m_sb.sb_rextsize, &mod);
|
||||
ASSERT(mod == 0);
|
||||
|
||||
error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
|
||||
error = xfs_rtfree_blocks(tp, del->br_startblock,
|
||||
del->br_blockcount);
|
||||
if (error)
|
||||
goto done;
|
||||
}
|
||||
|
||||
do_fx = 0;
|
||||
nblks = len * mp->m_sb.sb_rextsize;
|
||||
qfield = XFS_TRANS_DQ_RTBCOUNT;
|
||||
} else {
|
||||
do_fx = 1;
|
||||
nblks = del->br_blockcount;
|
||||
qfield = XFS_TRANS_DQ_BCOUNT;
|
||||
}
|
||||
nblks = del->br_blockcount;
|
||||
|
||||
del_endblock = del->br_startblock + del->br_blockcount;
|
||||
if (cur) {
|
||||
|
||||
@@ -245,26 +245,33 @@ xfs_defer_create_intents(
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC void
|
||||
xfs_defer_pending_abort(
|
||||
struct xfs_mount *mp,
|
||||
struct list_head *dop_list)
|
||||
{
|
||||
struct xfs_defer_pending *dfp;
|
||||
const struct xfs_defer_op_type *ops;
|
||||
|
||||
/* Abort intent items that don't have a done item. */
|
||||
list_for_each_entry(dfp, dop_list, dfp_list) {
|
||||
ops = defer_op_types[dfp->dfp_type];
|
||||
trace_xfs_defer_pending_abort(mp, dfp);
|
||||
if (dfp->dfp_intent && !dfp->dfp_done) {
|
||||
ops->abort_intent(dfp->dfp_intent);
|
||||
dfp->dfp_intent = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Abort all the intents that were committed. */
|
||||
STATIC void
|
||||
xfs_defer_trans_abort(
|
||||
struct xfs_trans *tp,
|
||||
struct list_head *dop_pending)
|
||||
{
|
||||
struct xfs_defer_pending *dfp;
|
||||
const struct xfs_defer_op_type *ops;
|
||||
|
||||
trace_xfs_defer_trans_abort(tp, _RET_IP_);
|
||||
|
||||
/* Abort intent items that don't have a done item. */
|
||||
list_for_each_entry(dfp, dop_pending, dfp_list) {
|
||||
ops = defer_op_types[dfp->dfp_type];
|
||||
trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
|
||||
if (dfp->dfp_intent && !dfp->dfp_done) {
|
||||
ops->abort_intent(dfp->dfp_intent);
|
||||
dfp->dfp_intent = NULL;
|
||||
}
|
||||
}
|
||||
xfs_defer_pending_abort(tp->t_mountp, dop_pending);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -756,12 +763,13 @@ xfs_defer_ops_capture(
|
||||
|
||||
/* Release all resources that we used to capture deferred ops. */
|
||||
void
|
||||
xfs_defer_ops_capture_free(
|
||||
xfs_defer_ops_capture_abort(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_defer_capture *dfc)
|
||||
{
|
||||
unsigned short i;
|
||||
|
||||
xfs_defer_pending_abort(mp, &dfc->dfc_dfops);
|
||||
xfs_defer_cancel_list(mp, &dfc->dfc_dfops);
|
||||
|
||||
for (i = 0; i < dfc->dfc_held.dr_bufs; i++)
|
||||
@@ -802,7 +810,7 @@ xfs_defer_ops_capture_and_commit(
|
||||
/* Commit the transaction and add the capture structure to the list. */
|
||||
error = xfs_trans_commit(tp);
|
||||
if (error) {
|
||||
xfs_defer_ops_capture_free(mp, dfc);
|
||||
xfs_defer_ops_capture_abort(mp, dfc);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ int xfs_defer_ops_capture_and_commit(struct xfs_trans *tp,
|
||||
struct list_head *capture_list);
|
||||
void xfs_defer_ops_continue(struct xfs_defer_capture *d, struct xfs_trans *tp,
|
||||
struct xfs_defer_resources *dres);
|
||||
void xfs_defer_ops_capture_free(struct xfs_mount *mp,
|
||||
void xfs_defer_ops_capture_abort(struct xfs_mount *mp,
|
||||
struct xfs_defer_capture *d);
|
||||
void xfs_defer_resources_rele(struct xfs_defer_resources *dres);
|
||||
|
||||
|
||||
@@ -508,6 +508,9 @@ xfs_dinode_verify(
|
||||
if (mode && nextents + naextents > nblocks)
|
||||
return __this_address;
|
||||
|
||||
if (nextents + naextents == 0 && nblocks != 0)
|
||||
return __this_address;
|
||||
|
||||
if (S_ISDIR(mode) && nextents > mp->m_dir_geo->max_extents)
|
||||
return __this_address;
|
||||
|
||||
|
||||
@@ -1005,6 +1005,39 @@ xfs_rtfree_extent(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free some blocks in the realtime subvolume. rtbno and rtlen are in units of
|
||||
* rt blocks, not rt extents; must be aligned to the rt extent size; and rtlen
|
||||
* cannot exceed XFS_MAX_BMBT_EXTLEN.
|
||||
*/
|
||||
int
|
||||
xfs_rtfree_blocks(
|
||||
struct xfs_trans *tp,
|
||||
xfs_fsblock_t rtbno,
|
||||
xfs_filblks_t rtlen)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
xfs_rtblock_t bno;
|
||||
xfs_filblks_t len;
|
||||
xfs_extlen_t mod;
|
||||
|
||||
ASSERT(rtlen <= XFS_MAX_BMBT_EXTLEN);
|
||||
|
||||
len = div_u64_rem(rtlen, mp->m_sb.sb_rextsize, &mod);
|
||||
if (mod) {
|
||||
ASSERT(mod == 0);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
bno = div_u64_rem(rtbno, mp->m_sb.sb_rextsize, &mod);
|
||||
if (mod) {
|
||||
ASSERT(mod == 0);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return xfs_rtfree_extent(tp, bno, len);
|
||||
}
|
||||
|
||||
/* Find all the free records within a given range. */
|
||||
int
|
||||
xfs_rtalloc_query_range(
|
||||
|
||||
@@ -25,7 +25,7 @@ extern uint64_t xfs_sb_version_to_features(struct xfs_sb *sbp);
|
||||
|
||||
extern int xfs_update_secondary_sbs(struct xfs_mount *mp);
|
||||
|
||||
#define XFS_FS_GEOM_MAX_STRUCT_VER (4)
|
||||
#define XFS_FS_GEOM_MAX_STRUCT_VER (5)
|
||||
extern void xfs_fs_geometry(struct xfs_mount *mp, struct xfs_fsop_geom *geo,
|
||||
int struct_version);
|
||||
extern int xfs_sb_read_secondary(struct xfs_mount *mp,
|
||||
|
||||
@@ -780,12 +780,10 @@ xfs_alloc_file_space(
|
||||
{
|
||||
xfs_mount_t *mp = ip->i_mount;
|
||||
xfs_off_t count;
|
||||
xfs_filblks_t allocated_fsb;
|
||||
xfs_filblks_t allocatesize_fsb;
|
||||
xfs_extlen_t extsz, temp;
|
||||
xfs_fileoff_t startoffset_fsb;
|
||||
xfs_fileoff_t endoffset_fsb;
|
||||
int nimaps;
|
||||
int rt;
|
||||
xfs_trans_t *tp;
|
||||
xfs_bmbt_irec_t imaps[1], *imapp;
|
||||
@@ -808,7 +806,6 @@ xfs_alloc_file_space(
|
||||
|
||||
count = len;
|
||||
imapp = &imaps[0];
|
||||
nimaps = 1;
|
||||
startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
endoffset_fsb = XFS_B_TO_FSB(mp, offset + count);
|
||||
allocatesize_fsb = endoffset_fsb - startoffset_fsb;
|
||||
@@ -819,6 +816,7 @@ xfs_alloc_file_space(
|
||||
while (allocatesize_fsb && !error) {
|
||||
xfs_fileoff_t s, e;
|
||||
unsigned int dblocks, rblocks, resblks;
|
||||
int nimaps = 1;
|
||||
|
||||
/*
|
||||
* Determine space reservations for data/realtime.
|
||||
@@ -884,15 +882,19 @@ xfs_alloc_file_space(
|
||||
if (error)
|
||||
break;
|
||||
|
||||
allocated_fsb = imapp->br_blockcount;
|
||||
|
||||
if (nimaps == 0) {
|
||||
error = -ENOSPC;
|
||||
break;
|
||||
/*
|
||||
* If the allocator cannot find a single free extent large
|
||||
* enough to cover the start block of the requested range,
|
||||
* xfs_bmapi_write will return 0 but leave *nimaps set to 0.
|
||||
*
|
||||
* In that case we simply need to keep looping with the same
|
||||
* startoffset_fsb so that one of the following allocations
|
||||
* will eventually reach the requested range.
|
||||
*/
|
||||
if (nimaps) {
|
||||
startoffset_fsb += imapp->br_blockcount;
|
||||
allocatesize_fsb -= imapp->br_blockcount;
|
||||
}
|
||||
|
||||
startoffset_fsb += allocated_fsb;
|
||||
allocatesize_fsb -= allocated_fsb;
|
||||
}
|
||||
|
||||
return error;
|
||||
|
||||
@@ -562,7 +562,8 @@ xfs_dquot_from_disk(
|
||||
struct xfs_dquot *dqp,
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
struct xfs_disk_dquot *ddqp = bp->b_addr + dqp->q_bufoffset;
|
||||
struct xfs_dqblk *dqb = xfs_buf_offset(bp, dqp->q_bufoffset);
|
||||
struct xfs_disk_dquot *ddqp = &dqb->dd_diskdq;
|
||||
|
||||
/*
|
||||
* Ensure that we got the type and ID we were looking for.
|
||||
@@ -1250,7 +1251,7 @@ xfs_qm_dqflush(
|
||||
}
|
||||
|
||||
/* Flush the incore dquot to the ondisk buffer. */
|
||||
dqblk = bp->b_addr + dqp->q_bufoffset;
|
||||
dqblk = xfs_buf_offset(bp, dqp->q_bufoffset);
|
||||
xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp);
|
||||
|
||||
/*
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_log_priv.h"
|
||||
#include "xfs_log_recover.h"
|
||||
#include "xfs_error.h"
|
||||
|
||||
STATIC void
|
||||
xlog_recover_dquot_ra_pass2(
|
||||
@@ -65,6 +66,7 @@ xlog_recover_dquot_commit_pass2(
|
||||
{
|
||||
struct xfs_mount *mp = log->l_mp;
|
||||
struct xfs_buf *bp;
|
||||
struct xfs_dqblk *dqb;
|
||||
struct xfs_disk_dquot *ddq, *recddq;
|
||||
struct xfs_dq_logformat *dq_f;
|
||||
xfs_failaddr_t fa;
|
||||
@@ -130,14 +132,14 @@ xlog_recover_dquot_commit_pass2(
|
||||
return error;
|
||||
|
||||
ASSERT(bp);
|
||||
ddq = xfs_buf_offset(bp, dq_f->qlf_boffset);
|
||||
dqb = xfs_buf_offset(bp, dq_f->qlf_boffset);
|
||||
ddq = &dqb->dd_diskdq;
|
||||
|
||||
/*
|
||||
* If the dquot has an LSN in it, recover the dquot only if it's less
|
||||
* than the lsn of the transaction we are replaying.
|
||||
*/
|
||||
if (xfs_has_crc(mp)) {
|
||||
struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddq;
|
||||
xfs_lsn_t lsn = be64_to_cpu(dqb->dd_lsn);
|
||||
|
||||
if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) {
|
||||
@@ -147,10 +149,23 @@ xlog_recover_dquot_commit_pass2(
|
||||
|
||||
memcpy(ddq, recddq, item->ri_buf[1].i_len);
|
||||
if (xfs_has_crc(mp)) {
|
||||
xfs_update_cksum((char *)ddq, sizeof(struct xfs_dqblk),
|
||||
xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
|
||||
XFS_DQUOT_CRC_OFF);
|
||||
}
|
||||
|
||||
/* Validate the recovered dquot. */
|
||||
fa = xfs_dqblk_verify(log->l_mp, dqb, dq_f->qlf_id);
|
||||
if (fa) {
|
||||
XFS_CORRUPTION_ERROR("Bad dquot after recovery",
|
||||
XFS_ERRLEVEL_LOW, mp, dqb,
|
||||
sizeof(struct xfs_dqblk));
|
||||
xfs_alert(mp,
|
||||
"Metadata corruption detected at %pS, dquot 0x%x",
|
||||
fa, dq_f->qlf_id);
|
||||
error = -EFSCORRUPTED;
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
ASSERT(dq_f->qlf_size == 2);
|
||||
ASSERT(bp->b_mount == mp);
|
||||
bp->b_flags |= _XBF_LOGRECOVERY;
|
||||
|
||||
@@ -214,6 +214,43 @@ xfs_ilock_iocb(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_ilock_iocb_for_write(
|
||||
struct kiocb *iocb,
|
||||
unsigned int *lock_mode)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp));
|
||||
|
||||
ret = xfs_ilock_iocb(iocb, *lock_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (*lock_mode == XFS_IOLOCK_EXCL)
|
||||
return 0;
|
||||
if (!xfs_iflags_test(ip, XFS_IREMAPPING))
|
||||
return 0;
|
||||
|
||||
xfs_iunlock(ip, *lock_mode);
|
||||
*lock_mode = XFS_IOLOCK_EXCL;
|
||||
return xfs_ilock_iocb(iocb, *lock_mode);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
xfs_ilock_for_write_fault(
|
||||
struct xfs_inode *ip)
|
||||
{
|
||||
/* get a shared lock if no remapping in progress */
|
||||
xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
|
||||
if (!xfs_iflags_test(ip, XFS_IREMAPPING))
|
||||
return XFS_MMAPLOCK_SHARED;
|
||||
|
||||
/* wait for remapping to complete */
|
||||
xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
|
||||
xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
|
||||
return XFS_MMAPLOCK_EXCL;
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
xfs_file_dio_read(
|
||||
struct kiocb *iocb,
|
||||
@@ -551,7 +588,7 @@ xfs_file_dio_write_aligned(
|
||||
unsigned int iolock = XFS_IOLOCK_SHARED;
|
||||
ssize_t ret;
|
||||
|
||||
ret = xfs_ilock_iocb(iocb, iolock);
|
||||
ret = xfs_ilock_iocb_for_write(iocb, &iolock);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = xfs_file_write_checks(iocb, from, &iolock);
|
||||
@@ -618,7 +655,7 @@ retry_exclusive:
|
||||
flags = IOMAP_DIO_FORCE_WAIT;
|
||||
}
|
||||
|
||||
ret = xfs_ilock_iocb(iocb, iolock);
|
||||
ret = xfs_ilock_iocb_for_write(iocb, &iolock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1180,7 +1217,7 @@ xfs_file_remap_range(
|
||||
if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out))
|
||||
xfs_log_force_inode(dest);
|
||||
out_unlock:
|
||||
xfs_iunlock2_io_mmap(src, dest);
|
||||
xfs_iunlock2_remapping(src, dest);
|
||||
if (ret)
|
||||
trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
|
||||
return remapped > 0 ? remapped : ret;
|
||||
@@ -1328,6 +1365,7 @@ __xfs_filemap_fault(
|
||||
struct inode *inode = file_inode(vmf->vma->vm_file);
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
vm_fault_t ret;
|
||||
unsigned int lock_mode = 0;
|
||||
|
||||
trace_xfs_filemap_fault(ip, order, write_fault);
|
||||
|
||||
@@ -1336,25 +1374,24 @@ __xfs_filemap_fault(
|
||||
file_update_time(vmf->vma->vm_file);
|
||||
}
|
||||
|
||||
if (IS_DAX(inode) || write_fault)
|
||||
lock_mode = xfs_ilock_for_write_fault(XFS_I(inode));
|
||||
|
||||
if (IS_DAX(inode)) {
|
||||
pfn_t pfn;
|
||||
|
||||
xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
|
||||
ret = xfs_dax_fault(vmf, order, write_fault, &pfn);
|
||||
if (ret & VM_FAULT_NEEDDSYNC)
|
||||
ret = dax_finish_sync_fault(vmf, order, pfn);
|
||||
xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
|
||||
} else if (write_fault) {
|
||||
ret = iomap_page_mkwrite(vmf, &xfs_page_mkwrite_iomap_ops);
|
||||
} else {
|
||||
if (write_fault) {
|
||||
xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
|
||||
ret = iomap_page_mkwrite(vmf,
|
||||
&xfs_page_mkwrite_iomap_ops);
|
||||
xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
|
||||
} else {
|
||||
ret = filemap_fault(vmf);
|
||||
}
|
||||
ret = filemap_fault(vmf);
|
||||
}
|
||||
|
||||
if (lock_mode)
|
||||
xfs_iunlock(XFS_I(inode), lock_mode);
|
||||
|
||||
if (write_fault)
|
||||
sb_end_pagefault(inode->i_sb);
|
||||
return ret;
|
||||
|
||||
@@ -918,6 +918,13 @@ xfs_droplink(
|
||||
xfs_trans_t *tp,
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
if (VFS_I(ip)->i_nlink == 0) {
|
||||
xfs_alert(ip->i_mount,
|
||||
"%s: Attempt to drop inode (%llu) with nlink zero.",
|
||||
__func__, ip->i_ino);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
|
||||
|
||||
drop_nlink(VFS_I(ip));
|
||||
@@ -3621,6 +3628,23 @@ xfs_iunlock2_io_mmap(
|
||||
inode_unlock(VFS_I(ip1));
|
||||
}
|
||||
|
||||
/* Drop the MMAPLOCK and the IOLOCK after a remap completes. */
|
||||
void
|
||||
xfs_iunlock2_remapping(
|
||||
struct xfs_inode *ip1,
|
||||
struct xfs_inode *ip2)
|
||||
{
|
||||
xfs_iflags_clear(ip1, XFS_IREMAPPING);
|
||||
|
||||
if (ip1 != ip2)
|
||||
xfs_iunlock(ip1, XFS_MMAPLOCK_SHARED);
|
||||
xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
|
||||
|
||||
if (ip1 != ip2)
|
||||
inode_unlock_shared(VFS_I(ip1));
|
||||
inode_unlock(VFS_I(ip2));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reload the incore inode list for this inode. Caller should ensure that
|
||||
* the link count cannot change, either by taking ILOCK_SHARED or otherwise
|
||||
|
||||
@@ -347,6 +347,14 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
|
||||
/* Quotacheck is running but inode has not been added to quota counts. */
|
||||
#define XFS_IQUOTAUNCHECKED (1 << 14)
|
||||
|
||||
/*
|
||||
* Remap in progress. Callers that wish to update file data while
|
||||
* holding a shared IOLOCK or MMAPLOCK must drop the lock and retake
|
||||
* the lock in exclusive mode. Relocking the file will block until
|
||||
* IREMAPPING is cleared.
|
||||
*/
|
||||
#define XFS_IREMAPPING (1U << 15)
|
||||
|
||||
/* All inode state flags related to inode reclaim. */
|
||||
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
|
||||
XFS_IRECLAIM | \
|
||||
@@ -561,6 +569,14 @@ extern void xfs_setup_inode(struct xfs_inode *ip);
|
||||
extern void xfs_setup_iops(struct xfs_inode *ip);
|
||||
extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init);
|
||||
|
||||
static inline void xfs_update_stable_writes(struct xfs_inode *ip)
|
||||
{
|
||||
if (bdev_stable_writes(xfs_inode_buftarg(ip)->bt_bdev))
|
||||
mapping_set_stable_writes(VFS_I(ip)->i_mapping);
|
||||
else
|
||||
mapping_clear_stable_writes(VFS_I(ip)->i_mapping);
|
||||
}
|
||||
|
||||
/*
|
||||
* When setting up a newly allocated inode, we need to call
|
||||
* xfs_finish_inode_setup() once the inode is fully instantiated at
|
||||
@@ -595,6 +611,7 @@ void xfs_end_io(struct work_struct *work);
|
||||
|
||||
int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
|
||||
void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
|
||||
void xfs_iunlock2_remapping(struct xfs_inode *ip1, struct xfs_inode *ip2);
|
||||
|
||||
static inline bool
|
||||
xfs_inode_unlinked_incomplete(
|
||||
|
||||
@@ -286,6 +286,7 @@ xlog_recover_inode_commit_pass2(
|
||||
struct xfs_log_dinode *ldip;
|
||||
uint isize;
|
||||
int need_free = 0;
|
||||
xfs_failaddr_t fa;
|
||||
|
||||
if (item->ri_buf[0].i_len == sizeof(struct xfs_inode_log_format)) {
|
||||
in_f = item->ri_buf[0].i_addr;
|
||||
@@ -530,8 +531,19 @@ out_owner_change:
|
||||
(dip->di_mode != 0))
|
||||
error = xfs_recover_inode_owner_change(mp, dip, in_f,
|
||||
buffer_list);
|
||||
/* re-generate the checksum. */
|
||||
/* re-generate the checksum and validate the recovered inode. */
|
||||
xfs_dinode_calc_crc(log->l_mp, dip);
|
||||
fa = xfs_dinode_verify(log->l_mp, in_f->ilf_ino, dip);
|
||||
if (fa) {
|
||||
XFS_CORRUPTION_ERROR(
|
||||
"Bad dinode after recovery",
|
||||
XFS_ERRLEVEL_LOW, mp, dip, sizeof(*dip));
|
||||
xfs_alert(mp,
|
||||
"Metadata corruption detected at %pS, inode 0x%llx",
|
||||
fa, in_f->ilf_ino);
|
||||
error = -EFSCORRUPTED;
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
ASSERT(bp->b_mount == mp);
|
||||
bp->b_flags |= _XBF_LOGRECOVERY;
|
||||
|
||||
@@ -1120,23 +1120,25 @@ xfs_ioctl_setattr_xflags(
|
||||
struct fileattr *fa)
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME);
|
||||
uint64_t i_flags2;
|
||||
|
||||
/* Can't change realtime flag if any extents are allocated. */
|
||||
if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
|
||||
XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
|
||||
return -EINVAL;
|
||||
|
||||
/* If realtime flag is set then must have realtime device */
|
||||
if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
|
||||
if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
|
||||
(ip->i_extsize % mp->m_sb.sb_rextsize))
|
||||
if (rtflag != XFS_IS_REALTIME_INODE(ip)) {
|
||||
/* Can't change realtime flag if any extents are allocated. */
|
||||
if (ip->i_df.if_nextents || ip->i_delayed_blks)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Clear reflink if we are actually able to set the rt flag. */
|
||||
if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip))
|
||||
ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
|
||||
if (rtflag) {
|
||||
/* If realtime flag is set then must have realtime device */
|
||||
if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
|
||||
(ip->i_extsize % mp->m_sb.sb_rextsize))
|
||||
return -EINVAL;
|
||||
|
||||
/* Clear reflink if we are actually able to set the rt flag. */
|
||||
if (xfs_is_reflink_inode(ip))
|
||||
ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
|
||||
}
|
||||
|
||||
/* diflags2 only valid for v3 inodes. */
|
||||
i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
|
||||
@@ -1147,6 +1149,14 @@ xfs_ioctl_setattr_xflags(
|
||||
ip->i_diflags2 = i_flags2;
|
||||
|
||||
xfs_diflags_to_iflags(ip, false);
|
||||
|
||||
/*
|
||||
* Make the stable writes flag match that of the device the inode
|
||||
* resides on when flipping the RT flag.
|
||||
*/
|
||||
if (rtflag != XFS_IS_REALTIME_INODE(ip) && S_ISREG(VFS_I(ip)->i_mode))
|
||||
xfs_update_stable_writes(ip);
|
||||
|
||||
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
XFS_STATS_INC(mp, xs_ig_attrchg);
|
||||
|
||||
@@ -1298,6 +1298,13 @@ xfs_setup_inode(
|
||||
gfp_mask = mapping_gfp_mask(inode->i_mapping);
|
||||
mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS)));
|
||||
|
||||
/*
|
||||
* For real-time inodes update the stable write flags to that of the RT
|
||||
* device instead of the data device.
|
||||
*/
|
||||
if (S_ISREG(inode->i_mode) && XFS_IS_REALTIME_INODE(ip))
|
||||
xfs_update_stable_writes(ip);
|
||||
|
||||
/*
|
||||
* If there is no attribute fork no ACL can exist on this inode,
|
||||
* and it can't have any file capabilities attached to it either.
|
||||
|
||||
@@ -1893,9 +1893,7 @@ xlog_write_iclog(
|
||||
* the buffer manually, the code needs to be kept in sync
|
||||
* with the I/O completion path.
|
||||
*/
|
||||
xlog_state_done_syncing(iclog);
|
||||
up(&iclog->ic_sema);
|
||||
return;
|
||||
goto sync;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1925,20 +1923,17 @@ xlog_write_iclog(
|
||||
* avoid shutdown re-entering this path and erroring out again.
|
||||
*/
|
||||
if (log->l_targ != log->l_mp->m_ddev_targp &&
|
||||
blkdev_issue_flush(log->l_mp->m_ddev_targp->bt_bdev)) {
|
||||
xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
|
||||
return;
|
||||
}
|
||||
blkdev_issue_flush(log->l_mp->m_ddev_targp->bt_bdev))
|
||||
goto shutdown;
|
||||
}
|
||||
if (iclog->ic_flags & XLOG_ICL_NEED_FUA)
|
||||
iclog->ic_bio.bi_opf |= REQ_FUA;
|
||||
|
||||
iclog->ic_flags &= ~(XLOG_ICL_NEED_FLUSH | XLOG_ICL_NEED_FUA);
|
||||
|
||||
if (xlog_map_iclog_data(&iclog->ic_bio, iclog->ic_data, count)) {
|
||||
xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
|
||||
return;
|
||||
}
|
||||
if (xlog_map_iclog_data(&iclog->ic_bio, iclog->ic_data, count))
|
||||
goto shutdown;
|
||||
|
||||
if (is_vmalloc_addr(iclog->ic_data))
|
||||
flush_kernel_vmap_range(iclog->ic_data, count);
|
||||
|
||||
@@ -1959,6 +1954,12 @@ xlog_write_iclog(
|
||||
}
|
||||
|
||||
submit_bio(&iclog->ic_bio);
|
||||
return;
|
||||
shutdown:
|
||||
xlog_force_shutdown(log, SHUTDOWN_LOG_IO_ERROR);
|
||||
sync:
|
||||
xlog_state_done_syncing(iclog);
|
||||
up(&iclog->ic_sema);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2511,7 +2511,7 @@ xlog_abort_defer_ops(
|
||||
|
||||
list_for_each_entry_safe(dfc, next, capture_list, dfc_list) {
|
||||
list_del_init(&dfc->dfc_list);
|
||||
xfs_defer_ops_capture_free(mp, dfc);
|
||||
xfs_defer_ops_capture_abort(mp, dfc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -784,6 +784,7 @@ xfs_reflink_end_cow_extent(
|
||||
}
|
||||
}
|
||||
del = got;
|
||||
xfs_trim_extent(&del, *offset_fsb, end_fsb - *offset_fsb);
|
||||
|
||||
/* Grab the corresponding mapping in the data fork. */
|
||||
nmaps = 1;
|
||||
@@ -1540,6 +1541,10 @@ xfs_reflink_remap_prep(
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
xfs_iflags_set(src, XFS_IREMAPPING);
|
||||
if (inode_in != inode_out)
|
||||
xfs_ilock_demote(src, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL);
|
||||
|
||||
return 0;
|
||||
out_unlock:
|
||||
xfs_iunlock2_io_mmap(src, dest);
|
||||
|
||||
@@ -211,6 +211,23 @@ xfs_rtallocate_range(
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we don't run off the end of the rt volume. Be careful that
|
||||
* adjusting maxlen downwards doesn't cause us to fail the alignment checks.
|
||||
*/
|
||||
static inline xfs_extlen_t
|
||||
xfs_rtallocate_clamp_len(
|
||||
struct xfs_mount *mp,
|
||||
xfs_rtblock_t startrtx,
|
||||
xfs_extlen_t rtxlen,
|
||||
xfs_extlen_t prod)
|
||||
{
|
||||
xfs_extlen_t ret;
|
||||
|
||||
ret = min(mp->m_sb.sb_rextents, startrtx + rtxlen) - startrtx;
|
||||
return rounddown(ret, prod);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to allocate an extent minlen<=len<=maxlen starting from
|
||||
* bitmap block bbno. If we don't get maxlen then use prod to trim
|
||||
@@ -248,7 +265,7 @@ xfs_rtallocate_extent_block(
|
||||
i <= end;
|
||||
i++) {
|
||||
/* Make sure we don't scan off the end of the rt volume. */
|
||||
maxlen = min(mp->m_sb.sb_rextents, i + maxlen) - i;
|
||||
maxlen = xfs_rtallocate_clamp_len(mp, i, maxlen, prod);
|
||||
|
||||
/*
|
||||
* See if there's a free extent of maxlen starting at i.
|
||||
@@ -355,7 +372,8 @@ xfs_rtallocate_extent_exact(
|
||||
int isfree; /* extent is free */
|
||||
xfs_rtblock_t next; /* next block to try (dummy) */
|
||||
|
||||
ASSERT(minlen % prod == 0 && maxlen % prod == 0);
|
||||
ASSERT(minlen % prod == 0);
|
||||
ASSERT(maxlen % prod == 0);
|
||||
/*
|
||||
* Check if the range in question (for maxlen) is free.
|
||||
*/
|
||||
@@ -438,7 +456,9 @@ xfs_rtallocate_extent_near(
|
||||
xfs_rtblock_t n; /* next block to try */
|
||||
xfs_rtblock_t r; /* result block */
|
||||
|
||||
ASSERT(minlen % prod == 0 && maxlen % prod == 0);
|
||||
ASSERT(minlen % prod == 0);
|
||||
ASSERT(maxlen % prod == 0);
|
||||
|
||||
/*
|
||||
* If the block number given is off the end, silently set it to
|
||||
* the last block.
|
||||
@@ -447,7 +467,7 @@ xfs_rtallocate_extent_near(
|
||||
bno = mp->m_sb.sb_rextents - 1;
|
||||
|
||||
/* Make sure we don't run off the end of the rt volume. */
|
||||
maxlen = min(mp->m_sb.sb_rextents, bno + maxlen) - bno;
|
||||
maxlen = xfs_rtallocate_clamp_len(mp, bno, maxlen, prod);
|
||||
if (maxlen < minlen) {
|
||||
*rtblock = NULLRTBLOCK;
|
||||
return 0;
|
||||
@@ -638,7 +658,8 @@ xfs_rtallocate_extent_size(
|
||||
xfs_rtblock_t r; /* result block number */
|
||||
xfs_suminfo_t sum; /* summary information for extents */
|
||||
|
||||
ASSERT(minlen % prod == 0 && maxlen % prod == 0);
|
||||
ASSERT(minlen % prod == 0);
|
||||
ASSERT(maxlen % prod == 0);
|
||||
ASSERT(maxlen != 0);
|
||||
|
||||
/*
|
||||
@@ -954,7 +975,7 @@ xfs_growfs_rt(
|
||||
return -EINVAL;
|
||||
|
||||
/* Unsupported realtime features. */
|
||||
if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp))
|
||||
if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp) || xfs_has_quota(mp))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
nrblocks = in->newblocks;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user