mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-12 08:48:48 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Pull sparc fixes from David Miller: "A couple small fixes for sparc including some THP brown-paper-bag material: 1) During the merging of all the THP support for various architectures, sparc missed adding a HAVE_ARCH_TRANSPARENT_HUGEPAGE to it's Kconfig, oops. 2) Sparc needs to be mindful of hugepages in get_user_pages_fast(). 3) Fix memory leak in SBUS probe, from Cong Ding. 4) The sunvdc virtual disk client driver has a test of the bitmask of vdisk server supported operations which was off by one bit" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: sunvdc: Fix off-by-one in generic_request(). sparc64: Fix get_user_pages_fast() wrt. THP. sparc64: Add missing HAVE_ARCH_TRANSPARENT_HUGEPAGE. sparc: kernel/sbus.c: fix memory leakage
This commit is contained in:
commit
11e7651432
@ -61,6 +61,7 @@ config SPARC64
|
||||
select HAVE_MEMBLOCK
|
||||
select HAVE_MEMBLOCK_NODE_MAP
|
||||
select HAVE_SYSCALL_WRAPPERS
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
|
@ -71,7 +71,6 @@
|
||||
#define PMD_PADDR _AC(0xfffffffe,UL)
|
||||
#define PMD_PADDR_SHIFT _AC(11,UL)
|
||||
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
#define PMD_ISHUGE _AC(0x00000001,UL)
|
||||
|
||||
/* This is the PMD layout when PMD_ISHUGE is set. With 4MB huge
|
||||
@ -86,7 +85,6 @@
|
||||
#define PMD_HUGE_ACCESSED _AC(0x00000080,UL)
|
||||
#define PMD_HUGE_EXEC _AC(0x00000040,UL)
|
||||
#define PMD_HUGE_SPLITTING _AC(0x00000020,UL)
|
||||
#endif
|
||||
|
||||
/* PGDs point to PMD tables which are 8K aligned. */
|
||||
#define PGD_PADDR _AC(0xfffffffc,UL)
|
||||
@ -628,6 +626,12 @@ static inline unsigned long pte_special(pte_t pte)
|
||||
return pte_val(pte) & _PAGE_SPECIAL;
|
||||
}
|
||||
|
||||
static inline int pmd_large(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & (PMD_ISHUGE | PMD_HUGE_PRESENT)) ==
|
||||
(PMD_ISHUGE | PMD_HUGE_PRESENT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
static inline int pmd_young(pmd_t pmd)
|
||||
{
|
||||
@ -646,12 +650,6 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
|
||||
return val >> (PAGE_SHIFT - PMD_PADDR_SHIFT);
|
||||
}
|
||||
|
||||
static inline int pmd_large(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & (PMD_ISHUGE | PMD_HUGE_PRESENT)) ==
|
||||
(PMD_ISHUGE | PMD_HUGE_PRESENT);
|
||||
}
|
||||
|
||||
static inline int pmd_trans_splitting(pmd_t pmd)
|
||||
{
|
||||
return (pmd_val(pmd) & (PMD_ISHUGE|PMD_HUGE_SPLITTING)) ==
|
||||
|
@ -554,10 +554,8 @@ static void __init sbus_iommu_init(struct platform_device *op)
|
||||
regs = pr->phys_addr;
|
||||
|
||||
iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC);
|
||||
if (!iommu)
|
||||
goto fatal_memory_error;
|
||||
strbuf = kzalloc(sizeof(*strbuf), GFP_ATOMIC);
|
||||
if (!strbuf)
|
||||
if (!iommu || !strbuf)
|
||||
goto fatal_memory_error;
|
||||
|
||||
op->dev.archdata.iommu = iommu;
|
||||
@ -656,6 +654,8 @@ static void __init sbus_iommu_init(struct platform_device *op)
|
||||
return;
|
||||
|
||||
fatal_memory_error:
|
||||
kfree(iommu);
|
||||
kfree(strbuf);
|
||||
prom_printf("sbus_iommu_init: Fatal memory allocation error.\n");
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,56 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
|
||||
unsigned long end, int write, struct page **pages,
|
||||
int *nr)
|
||||
{
|
||||
struct page *head, *page, *tail;
|
||||
u32 mask;
|
||||
int refs;
|
||||
|
||||
mask = PMD_HUGE_PRESENT;
|
||||
if (write)
|
||||
mask |= PMD_HUGE_WRITE;
|
||||
if ((pmd_val(pmd) & mask) != mask)
|
||||
return 0;
|
||||
|
||||
refs = 0;
|
||||
head = pmd_page(pmd);
|
||||
page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
|
||||
tail = page;
|
||||
do {
|
||||
VM_BUG_ON(compound_head(page) != head);
|
||||
pages[*nr] = page;
|
||||
(*nr)++;
|
||||
page++;
|
||||
refs++;
|
||||
} while (addr += PAGE_SIZE, addr != end);
|
||||
|
||||
if (!page_cache_add_speculative(head, refs)) {
|
||||
*nr -= refs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlikely(pmd_val(pmd) != pmd_val(*pmdp))) {
|
||||
*nr -= refs;
|
||||
while (refs--)
|
||||
put_page(head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Any tail page need their mapcount reference taken before we
|
||||
* return.
|
||||
*/
|
||||
while (refs--) {
|
||||
if (PageTail(tail))
|
||||
get_huge_page_tail(tail);
|
||||
tail++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
|
||||
int write, struct page **pages, int *nr)
|
||||
{
|
||||
@ -77,9 +127,14 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
|
||||
pmd_t pmd = *pmdp;
|
||||
|
||||
next = pmd_addr_end(addr, end);
|
||||
if (pmd_none(pmd))
|
||||
if (pmd_none(pmd) || pmd_trans_splitting(pmd))
|
||||
return 0;
|
||||
if (!gup_pte_range(pmd, addr, next, write, pages, nr))
|
||||
if (unlikely(pmd_large(pmd))) {
|
||||
if (!gup_huge_pmd(pmdp, pmd, addr, next,
|
||||
write, pages, nr))
|
||||
return 0;
|
||||
} else if (!gup_pte_range(pmd, addr, next, write,
|
||||
pages, nr))
|
||||
return 0;
|
||||
} while (pmdp++, addr = next, addr != end);
|
||||
|
||||
|
@ -461,7 +461,7 @@ static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
|
||||
int op_len, err;
|
||||
void *req_buf;
|
||||
|
||||
if (!(((u64)1 << ((u64)op - 1)) & port->operations))
|
||||
if (!(((u64)1 << (u64)op) & port->operations))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (op) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user