mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge branch 'akpm' (patches from Andrew)
Pull updates from Andrew Morton: "Most of -mm and quite a number of other subsystems: hotfixes, scripts, ocfs2, misc, lib, binfmt, init, reiserfs, exec, dma-mapping, kcov. MM is fairly quiet this time. Holidays, I assume" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (118 commits) kcov: ignore fault-inject and stacktrace include/linux/io-mapping.h-mapping: use PHYS_PFN() macro in io_mapping_map_atomic_wc() execve: warn if process starts with executable stack reiserfs: prevent NULL pointer dereference in reiserfs_insert_item() init/main.c: fix misleading "This architecture does not have kernel memory protection" message init/main.c: fix quoted value handling in unknown_bootoption init/main.c: remove unnecessary repair_env_string in do_initcall_level init/main.c: log arguments and environment passed to init fs/binfmt_elf.c: coredump: allow process with empty address space to coredump fs/binfmt_elf.c: coredump: delete duplicated overflow check fs/binfmt_elf.c: coredump: allocate core ELF header on stack fs/binfmt_elf.c: make BAD_ADDR() unlikely fs/binfmt_elf.c: better codegen around current->mm fs/binfmt_elf.c: don't copy ELF header around fs/binfmt_elf.c: fix ->start_code calculation fs/binfmt_elf.c: smaller code generation around auxv vector fill lib/find_bit.c: uninline helper _find_next_bit() lib/find_bit.c: join _find_next_bit{_le} uapi: rename ext2_swab() to swab() and share globally in swab.h lib/scatterlist.c: adjust indentation in __sg_alloc_table ...
This commit is contained in:
@@ -834,6 +834,18 @@
|
||||
dump out devices still on the deferred probe list after
|
||||
retrying.
|
||||
|
||||
dfltcc= [HW,S390]
|
||||
Format: { on | off | def_only | inf_only | always }
|
||||
on: s390 zlib hardware support for compression on
|
||||
level 1 and decompression (default)
|
||||
off: No s390 zlib hardware support
|
||||
def_only: s390 zlib hardware support for deflate
|
||||
only (compression on level 1)
|
||||
inf_only: s390 zlib hardware support for inflate
|
||||
only (decompression)
|
||||
always: Same as 'on' but ignores the selected compression
|
||||
level always using hardware support (used for debugging)
|
||||
|
||||
dhash_entries= [KNL]
|
||||
Set number of hash buckets for dentry cache.
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ Core utilities
|
||||
generic-radix-tree
|
||||
memory-allocation
|
||||
mm-api
|
||||
pin_user_pages
|
||||
gfp_mask-from-fs-io
|
||||
timekeeping
|
||||
boot-time-mm
|
||||
|
||||
232
Documentation/core-api/pin_user_pages.rst
Normal file
232
Documentation/core-api/pin_user_pages.rst
Normal file
@@ -0,0 +1,232 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
====================================================
|
||||
pin_user_pages() and related calls
|
||||
====================================================
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
This document describes the following functions::
|
||||
|
||||
pin_user_pages()
|
||||
pin_user_pages_fast()
|
||||
pin_user_pages_remote()
|
||||
|
||||
Basic description of FOLL_PIN
|
||||
=============================
|
||||
|
||||
FOLL_PIN and FOLL_LONGTERM are flags that can be passed to the get_user_pages*()
|
||||
("gup") family of functions. FOLL_PIN has significant interactions and
|
||||
interdependencies with FOLL_LONGTERM, so both are covered here.
|
||||
|
||||
FOLL_PIN is internal to gup, meaning that it should not appear at the gup call
|
||||
sites. This allows the associated wrapper functions (pin_user_pages*() and
|
||||
others) to set the correct combination of these flags, and to check for problems
|
||||
as well.
|
||||
|
||||
FOLL_LONGTERM, on the other hand, *is* allowed to be set at the gup call sites.
|
||||
This is in order to avoid creating a large number of wrapper functions to cover
|
||||
all combinations of get*(), pin*(), FOLL_LONGTERM, and more. Also, the
|
||||
pin_user_pages*() APIs are clearly distinct from the get_user_pages*() APIs, so
|
||||
that's a natural dividing line, and a good point to make separate wrapper calls.
|
||||
In other words, use pin_user_pages*() for DMA-pinned pages, and
|
||||
get_user_pages*() for other cases. There are four cases described later on in
|
||||
this document, to further clarify that concept.
|
||||
|
||||
FOLL_PIN and FOLL_GET are mutually exclusive for a given gup call. However,
|
||||
multiple threads and call sites are free to pin the same struct pages, via both
|
||||
FOLL_PIN and FOLL_GET. It's just the call site that needs to choose one or the
|
||||
other, not the struct page(s).
|
||||
|
||||
The FOLL_PIN implementation is nearly the same as FOLL_GET, except that FOLL_PIN
|
||||
uses a different reference counting technique.
|
||||
|
||||
FOLL_PIN is a prerequisite to FOLL_LONGTERM. Another way of saying that is,
|
||||
FOLL_LONGTERM is a specific case, more restrictive case of FOLL_PIN.
|
||||
|
||||
Which flags are set by each wrapper
|
||||
===================================
|
||||
|
||||
For these pin_user_pages*() functions, FOLL_PIN is OR'd in with whatever gup
|
||||
flags the caller provides. The caller is required to pass in a non-null struct
|
||||
pages* array, and the function then pin pages by incrementing each by a special
|
||||
value. For now, that value is +1, just like get_user_pages*().::
|
||||
|
||||
Function
|
||||
--------
|
||||
pin_user_pages FOLL_PIN is always set internally by this function.
|
||||
pin_user_pages_fast FOLL_PIN is always set internally by this function.
|
||||
pin_user_pages_remote FOLL_PIN is always set internally by this function.
|
||||
|
||||
For these get_user_pages*() functions, FOLL_GET might not even be specified.
|
||||
Behavior is a little more complex than above. If FOLL_GET was *not* specified,
|
||||
but the caller passed in a non-null struct pages* array, then the function
|
||||
sets FOLL_GET for you, and proceeds to pin pages by incrementing the refcount
|
||||
of each page by +1.::
|
||||
|
||||
Function
|
||||
--------
|
||||
get_user_pages FOLL_GET is sometimes set internally by this function.
|
||||
get_user_pages_fast FOLL_GET is sometimes set internally by this function.
|
||||
get_user_pages_remote FOLL_GET is sometimes set internally by this function.
|
||||
|
||||
Tracking dma-pinned pages
|
||||
=========================
|
||||
|
||||
Some of the key design constraints, and solutions, for tracking dma-pinned
|
||||
pages:
|
||||
|
||||
* An actual reference count, per struct page, is required. This is because
|
||||
multiple processes may pin and unpin a page.
|
||||
|
||||
* False positives (reporting that a page is dma-pinned, when in fact it is not)
|
||||
are acceptable, but false negatives are not.
|
||||
|
||||
* struct page may not be increased in size for this, and all fields are already
|
||||
used.
|
||||
|
||||
* Given the above, we can overload the page->_refcount field by using, sort of,
|
||||
the upper bits in that field for a dma-pinned count. "Sort of", means that,
|
||||
rather than dividing page->_refcount into bit fields, we simple add a medium-
|
||||
large value (GUP_PIN_COUNTING_BIAS, initially chosen to be 1024: 10 bits) to
|
||||
page->_refcount. This provides fuzzy behavior: if a page has get_page() called
|
||||
on it 1024 times, then it will appear to have a single dma-pinned count.
|
||||
And again, that's acceptable.
|
||||
|
||||
This also leads to limitations: there are only 31-10==21 bits available for a
|
||||
counter that increments 10 bits at a time.
|
||||
|
||||
TODO: for 1GB and larger huge pages, this is cutting it close. That's because
|
||||
when pin_user_pages() follows such pages, it increments the head page by "1"
|
||||
(where "1" used to mean "+1" for get_user_pages(), but now means "+1024" for
|
||||
pin_user_pages()) for each tail page. So if you have a 1GB huge page:
|
||||
|
||||
* There are 256K (18 bits) worth of 4 KB tail pages.
|
||||
* There are 21 bits available to count up via GUP_PIN_COUNTING_BIAS (that is,
|
||||
10 bits at a time)
|
||||
* There are 21 - 18 == 3 bits available to count. Except that there aren't,
|
||||
because you need to allow for a few normal get_page() calls on the head page,
|
||||
as well. Fortunately, the approach of using addition, rather than "hard"
|
||||
bitfields, within page->_refcount, allows for sharing these bits gracefully.
|
||||
But we're still looking at about 8 references.
|
||||
|
||||
This, however, is a missing feature more than anything else, because it's easily
|
||||
solved by addressing an obvious inefficiency in the original get_user_pages()
|
||||
approach of retrieving pages: stop treating all the pages as if they were
|
||||
PAGE_SIZE. Retrieve huge pages as huge pages. The callers need to be aware of
|
||||
this, so some work is required. Once that's in place, this limitation mostly
|
||||
disappears from view, because there will be ample refcounting range available.
|
||||
|
||||
* Callers must specifically request "dma-pinned tracking of pages". In other
|
||||
words, just calling get_user_pages() will not suffice; a new set of functions,
|
||||
pin_user_page() and related, must be used.
|
||||
|
||||
FOLL_PIN, FOLL_GET, FOLL_LONGTERM: when to use which flags
|
||||
==========================================================
|
||||
|
||||
Thanks to Jan Kara, Vlastimil Babka and several other -mm people, for describing
|
||||
these categories:
|
||||
|
||||
CASE 1: Direct IO (DIO)
|
||||
-----------------------
|
||||
There are GUP references to pages that are serving
|
||||
as DIO buffers. These buffers are needed for a relatively short time (so they
|
||||
are not "long term"). No special synchronization with page_mkclean() or
|
||||
munmap() is provided. Therefore, flags to set at the call site are: ::
|
||||
|
||||
FOLL_PIN
|
||||
|
||||
...but rather than setting FOLL_PIN directly, call sites should use one of
|
||||
the pin_user_pages*() routines that set FOLL_PIN.
|
||||
|
||||
CASE 2: RDMA
|
||||
------------
|
||||
There are GUP references to pages that are serving as DMA
|
||||
buffers. These buffers are needed for a long time ("long term"). No special
|
||||
synchronization with page_mkclean() or munmap() is provided. Therefore, flags
|
||||
to set at the call site are: ::
|
||||
|
||||
FOLL_PIN | FOLL_LONGTERM
|
||||
|
||||
NOTE: Some pages, such as DAX pages, cannot be pinned with longterm pins. That's
|
||||
because DAX pages do not have a separate page cache, and so "pinning" implies
|
||||
locking down file system blocks, which is not (yet) supported in that way.
|
||||
|
||||
CASE 3: Hardware with page faulting support
|
||||
-------------------------------------------
|
||||
Here, a well-written driver doesn't normally need to pin pages at all. However,
|
||||
if the driver does choose to do so, it can register MMU notifiers for the range,
|
||||
and will be called back upon invalidation. Either way (avoiding page pinning, or
|
||||
using MMU notifiers to unpin upon request), there is proper synchronization with
|
||||
both filesystem and mm (page_mkclean(), munmap(), etc).
|
||||
|
||||
Therefore, neither flag needs to be set.
|
||||
|
||||
In this case, ideally, neither get_user_pages() nor pin_user_pages() should be
|
||||
called. Instead, the software should be written so that it does not pin pages.
|
||||
This allows mm and filesystems to operate more efficiently and reliably.
|
||||
|
||||
CASE 4: Pinning for struct page manipulation only
|
||||
-------------------------------------------------
|
||||
Here, normal GUP calls are sufficient, so neither flag needs to be set.
|
||||
|
||||
page_dma_pinned(): the whole point of pinning
|
||||
=============================================
|
||||
|
||||
The whole point of marking pages as "DMA-pinned" or "gup-pinned" is to be able
|
||||
to query, "is this page DMA-pinned?" That allows code such as page_mkclean()
|
||||
(and file system writeback code in general) to make informed decisions about
|
||||
what to do when a page cannot be unmapped due to such pins.
|
||||
|
||||
What to do in those cases is the subject of a years-long series of discussions
|
||||
and debates (see the References at the end of this document). It's a TODO item
|
||||
here: fill in the details once that's worked out. Meanwhile, it's safe to say
|
||||
that having this available: ::
|
||||
|
||||
static inline bool page_dma_pinned(struct page *page)
|
||||
|
||||
...is a prerequisite to solving the long-running gup+DMA problem.
|
||||
|
||||
Another way of thinking about FOLL_GET, FOLL_PIN, and FOLL_LONGTERM
|
||||
===================================================================
|
||||
|
||||
Another way of thinking about these flags is as a progression of restrictions:
|
||||
FOLL_GET is for struct page manipulation, without affecting the data that the
|
||||
struct page refers to. FOLL_PIN is a *replacement* for FOLL_GET, and is for
|
||||
short term pins on pages whose data *will* get accessed. As such, FOLL_PIN is
|
||||
a "more severe" form of pinning. And finally, FOLL_LONGTERM is an even more
|
||||
restrictive case that has FOLL_PIN as a prerequisite: this is for pages that
|
||||
will be pinned longterm, and whose data will be accessed.
|
||||
|
||||
Unit testing
|
||||
============
|
||||
This file::
|
||||
|
||||
tools/testing/selftests/vm/gup_benchmark.c
|
||||
|
||||
has the following new calls to exercise the new pin*() wrapper functions:
|
||||
|
||||
* PIN_FAST_BENCHMARK (./gup_benchmark -a)
|
||||
* PIN_BENCHMARK (./gup_benchmark -b)
|
||||
|
||||
You can monitor how many total dma-pinned pages have been acquired and released
|
||||
since the system was booted, via two new /proc/vmstat entries: ::
|
||||
|
||||
/proc/vmstat/nr_foll_pin_requested
|
||||
/proc/vmstat/nr_foll_pin_requested
|
||||
|
||||
Those are both going to show zero, unless CONFIG_DEBUG_VM is set. This is
|
||||
because there is a noticeable performance drop in unpin_user_page(), when they
|
||||
are activated.
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
* `Some slow progress on get_user_pages() (Apr 2, 2019) <https://lwn.net/Articles/784574/>`_
|
||||
* `DMA and get_user_pages() (LPC: Dec 12, 2018) <https://lwn.net/Articles/774411/>`_
|
||||
* `The trouble with get_user_pages() (Apr 30, 2018) <https://lwn.net/Articles/753027/>`_
|
||||
|
||||
John Hubbard, October, 2019
|
||||
@@ -130,6 +130,19 @@ checking for the same-value filled pages during store operation. However, the
|
||||
existing pages which are marked as same-value filled pages remain stored
|
||||
unchanged in zswap until they are either loaded or invalidated.
|
||||
|
||||
To prevent zswap from shrinking pool when zswap is full and there's a high
|
||||
pressure on swap (this will result in flipping pages in and out zswap pool
|
||||
without any real benefit but with a performance drop for the system), a
|
||||
special parameter has been introduced to implement a sort of hysteresis to
|
||||
refuse taking pages into zswap pool until it has sufficient space if the limit
|
||||
has been hit. To set the threshold at which zswap would start accepting pages
|
||||
again after it became full, use the sysfs ``accept_threhsold_percent``
|
||||
attribute, e. g.::
|
||||
|
||||
echo 80 > /sys/module/zswap/parameters/accept_threhsold_percent
|
||||
|
||||
Setting this parameter to 100 will disable the hysteresis.
|
||||
|
||||
A debugfs interface is provided for various statistic about pool size, number
|
||||
of pages stored, same-value filled pages and various counters for the reasons
|
||||
pages are rejected.
|
||||
|
||||
@@ -103,7 +103,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
|
||||
for (entry = 0; entry < entries; entry += chunk) {
|
||||
unsigned long n = min(entries - entry, chunk);
|
||||
|
||||
ret = get_user_pages(ua + (entry << PAGE_SHIFT), n,
|
||||
ret = pin_user_pages(ua + (entry << PAGE_SHIFT), n,
|
||||
FOLL_WRITE | FOLL_LONGTERM,
|
||||
mem->hpages + entry, NULL);
|
||||
if (ret == n) {
|
||||
@@ -167,9 +167,8 @@ good_exit:
|
||||
return 0;
|
||||
|
||||
free_exit:
|
||||
/* free the reference taken */
|
||||
for (i = 0; i < pinned; i++)
|
||||
put_page(mem->hpages[i]);
|
||||
/* free the references taken */
|
||||
unpin_user_pages(mem->hpages, pinned);
|
||||
|
||||
vfree(mem->hpas);
|
||||
kfree(mem);
|
||||
@@ -215,7 +214,8 @@ static void mm_iommu_unpin(struct mm_iommu_table_group_mem_t *mem)
|
||||
if (mem->hpas[i] & MM_IOMMU_TABLE_GROUP_PAGE_DIRTY)
|
||||
SetPageDirty(page);
|
||||
|
||||
put_page(page);
|
||||
unpin_user_page(page);
|
||||
|
||||
mem->hpas[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,13 +30,13 @@ extern unsigned char _compressed_start[];
|
||||
extern unsigned char _compressed_end[];
|
||||
|
||||
#ifdef CONFIG_HAVE_KERNEL_BZIP2
|
||||
#define HEAP_SIZE 0x400000
|
||||
#define BOOT_HEAP_SIZE 0x400000
|
||||
#else
|
||||
#define HEAP_SIZE 0x10000
|
||||
#define BOOT_HEAP_SIZE 0x10000
|
||||
#endif
|
||||
|
||||
static unsigned long free_mem_ptr = (unsigned long) _end;
|
||||
static unsigned long free_mem_end_ptr = (unsigned long) _end + HEAP_SIZE;
|
||||
static unsigned long free_mem_end_ptr = (unsigned long) _end + BOOT_HEAP_SIZE;
|
||||
|
||||
#ifdef CONFIG_KERNEL_GZIP
|
||||
#include "../../../../lib/decompress_inflate.c"
|
||||
@@ -62,7 +62,7 @@ static unsigned long free_mem_end_ptr = (unsigned long) _end + HEAP_SIZE;
|
||||
#include "../../../../lib/decompress_unxz.c"
|
||||
#endif
|
||||
|
||||
#define decompress_offset ALIGN((unsigned long)_end + HEAP_SIZE, PAGE_SIZE)
|
||||
#define decompress_offset ALIGN((unsigned long)_end + BOOT_HEAP_SIZE, PAGE_SIZE)
|
||||
|
||||
unsigned long mem_safe_offset(void)
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
|
||||
struct ipl_parameter_block __bootdata_preserved(ipl_block);
|
||||
int __bootdata_preserved(ipl_block_valid);
|
||||
unsigned int __bootdata_preserved(zlib_dfltcc_support) = ZLIB_DFLTCC_FULL;
|
||||
|
||||
unsigned long __bootdata(vmalloc_size) = VMALLOC_DEFAULT_SIZE;
|
||||
unsigned long __bootdata(memory_end);
|
||||
@@ -229,6 +230,19 @@ void parse_boot_command_line(void)
|
||||
if (!strcmp(param, "vmalloc") && val)
|
||||
vmalloc_size = round_up(memparse(val, NULL), PAGE_SIZE);
|
||||
|
||||
if (!strcmp(param, "dfltcc")) {
|
||||
if (!strcmp(val, "off"))
|
||||
zlib_dfltcc_support = ZLIB_DFLTCC_DISABLED;
|
||||
else if (!strcmp(val, "on"))
|
||||
zlib_dfltcc_support = ZLIB_DFLTCC_FULL;
|
||||
else if (!strcmp(val, "def_only"))
|
||||
zlib_dfltcc_support = ZLIB_DFLTCC_DEFLATE_ONLY;
|
||||
else if (!strcmp(val, "inf_only"))
|
||||
zlib_dfltcc_support = ZLIB_DFLTCC_INFLATE_ONLY;
|
||||
else if (!strcmp(val, "always"))
|
||||
zlib_dfltcc_support = ZLIB_DFLTCC_FULL_DEBUG;
|
||||
}
|
||||
|
||||
if (!strcmp(param, "noexec")) {
|
||||
rc = kstrtobool(val, &enabled);
|
||||
if (!rc && !enabled)
|
||||
|
||||
@@ -79,6 +79,13 @@ struct parmarea {
|
||||
char command_line[ARCH_COMMAND_LINE_SIZE]; /* 0x10480 */
|
||||
};
|
||||
|
||||
extern unsigned int zlib_dfltcc_support;
|
||||
#define ZLIB_DFLTCC_DISABLED 0
|
||||
#define ZLIB_DFLTCC_FULL 1
|
||||
#define ZLIB_DFLTCC_DEFLATE_ONLY 2
|
||||
#define ZLIB_DFLTCC_INFLATE_ONLY 3
|
||||
#define ZLIB_DFLTCC_FULL_DEBUG 4
|
||||
|
||||
extern int noexec_disabled;
|
||||
extern int memory_end_set;
|
||||
extern unsigned long memory_end;
|
||||
|
||||
@@ -111,6 +111,8 @@ unsigned long __bootdata_preserved(__etext_dma);
|
||||
unsigned long __bootdata_preserved(__sdma);
|
||||
unsigned long __bootdata_preserved(__edma);
|
||||
unsigned long __bootdata_preserved(__kaslr_offset);
|
||||
unsigned int __bootdata_preserved(zlib_dfltcc_support);
|
||||
EXPORT_SYMBOL(zlib_dfltcc_support);
|
||||
|
||||
unsigned long VMALLOC_START;
|
||||
EXPORT_SYMBOL(VMALLOC_START);
|
||||
@@ -759,14 +761,6 @@ static void __init free_mem_detect_info(void)
|
||||
memblock_free(start, size);
|
||||
}
|
||||
|
||||
static void __init memblock_physmem_add(phys_addr_t start, phys_addr_t size)
|
||||
{
|
||||
memblock_dbg("memblock_physmem_add: [%#016llx-%#016llx]\n",
|
||||
start, start + size - 1);
|
||||
memblock_add_range(&memblock.memory, start, size, 0, 0);
|
||||
memblock_add_range(&memblock.physmem, start, size, 0, 0);
|
||||
}
|
||||
|
||||
static const char * __init get_mem_info_source(void)
|
||||
{
|
||||
switch (mem_detect.info_source) {
|
||||
@@ -791,8 +785,10 @@ static void __init memblock_add_mem_detect_info(void)
|
||||
get_mem_info_source(), mem_detect.info_source);
|
||||
/* keep memblock lists close to the kernel */
|
||||
memblock_set_bottom_up(true);
|
||||
for_each_mem_detect_block(i, &start, &end)
|
||||
for_each_mem_detect_block(i, &start, &end) {
|
||||
memblock_add(start, end - start);
|
||||
memblock_physmem_add(start, end - start);
|
||||
}
|
||||
memblock_set_bottom_up(false);
|
||||
memblock_dump_all();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
@@ -172,7 +173,7 @@ struct acpi_thermal {
|
||||
struct acpi_handle_list devices;
|
||||
struct thermal_zone_device *thermal_zone;
|
||||
int tz_enabled;
|
||||
int kelvin_offset;
|
||||
int kelvin_offset; /* in millidegrees */
|
||||
struct work_struct thermal_check_work;
|
||||
};
|
||||
|
||||
@@ -297,7 +298,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
if (crt == -1) {
|
||||
tz->trips.critical.flags.valid = 0;
|
||||
} else if (crt > 0) {
|
||||
unsigned long crt_k = CELSIUS_TO_DECI_KELVIN(crt);
|
||||
unsigned long crt_k = celsius_to_deci_kelvin(crt);
|
||||
|
||||
/*
|
||||
* Allow override critical threshold
|
||||
*/
|
||||
@@ -333,7 +335,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
if (psv == -1) {
|
||||
status = AE_SUPPORT;
|
||||
} else if (psv > 0) {
|
||||
tmp = CELSIUS_TO_DECI_KELVIN(psv);
|
||||
tmp = celsius_to_deci_kelvin(psv);
|
||||
status = AE_OK;
|
||||
} else {
|
||||
status = acpi_evaluate_integer(tz->device->handle,
|
||||
@@ -413,7 +415,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
break;
|
||||
if (i == 1)
|
||||
tz->trips.active[0].temperature =
|
||||
CELSIUS_TO_DECI_KELVIN(act);
|
||||
celsius_to_deci_kelvin(act);
|
||||
else
|
||||
/*
|
||||
* Don't allow override higher than
|
||||
@@ -421,9 +423,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
|
||||
*/
|
||||
tz->trips.active[i - 1].temperature =
|
||||
(tz->trips.active[i - 2].temperature <
|
||||
CELSIUS_TO_DECI_KELVIN(act) ?
|
||||
celsius_to_deci_kelvin(act) ?
|
||||
tz->trips.active[i - 2].temperature :
|
||||
CELSIUS_TO_DECI_KELVIN(act));
|
||||
celsius_to_deci_kelvin(act));
|
||||
break;
|
||||
} else {
|
||||
tz->trips.active[i].temperature = tmp;
|
||||
@@ -519,7 +521,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(tz->temperature,
|
||||
*temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
}
|
||||
@@ -624,7 +626,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
|
||||
if (tz->trips.critical.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
*temp = deci_kelvin_to_millicelsius_with_offset(
|
||||
tz->trips.critical.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
@@ -634,7 +636,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
|
||||
if (tz->trips.hot.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
*temp = deci_kelvin_to_millicelsius_with_offset(
|
||||
tz->trips.hot.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
@@ -644,7 +646,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
|
||||
if (tz->trips.passive.flags.valid) {
|
||||
if (!trip) {
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
*temp = deci_kelvin_to_millicelsius_with_offset(
|
||||
tz->trips.passive.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
@@ -655,7 +657,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
|
||||
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
|
||||
tz->trips.active[i].flags.valid; i++) {
|
||||
if (!trip) {
|
||||
*temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
*temp = deci_kelvin_to_millicelsius_with_offset(
|
||||
tz->trips.active[i].temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
@@ -672,7 +674,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
|
||||
struct acpi_thermal *tz = thermal->devdata;
|
||||
|
||||
if (tz->trips.critical.flags.valid) {
|
||||
*temperature = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
*temperature = deci_kelvin_to_millicelsius_with_offset(
|
||||
tz->trips.critical.temperature,
|
||||
tz->kelvin_offset);
|
||||
return 0;
|
||||
@@ -692,7 +694,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
|
||||
|
||||
if (type == THERMAL_TRIP_ACTIVE) {
|
||||
int trip_temp;
|
||||
int temp = DECI_KELVIN_TO_MILLICELSIUS_WITH_OFFSET(
|
||||
int temp = deci_kelvin_to_millicelsius_with_offset(
|
||||
tz->temperature, tz->kelvin_offset);
|
||||
if (thermal_get_trip_temp(thermal, trip, &trip_temp))
|
||||
return -EINVAL;
|
||||
@@ -1043,9 +1045,9 @@ static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
|
||||
{
|
||||
if (tz->trips.critical.flags.valid &&
|
||||
(tz->trips.critical.temperature % 5) == 1)
|
||||
tz->kelvin_offset = 2731;
|
||||
tz->kelvin_offset = 273100;
|
||||
else
|
||||
tz->kelvin_offset = 2732;
|
||||
tz->kelvin_offset = 273200;
|
||||
}
|
||||
|
||||
static void acpi_thermal_check_fn(struct work_struct *work)
|
||||
@@ -1087,7 +1089,7 @@ static int acpi_thermal_add(struct acpi_device *device)
|
||||
INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
|
||||
|
||||
pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
|
||||
acpi_device_bid(device), DECI_KELVIN_TO_CELSIUS(tz->temperature));
|
||||
acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature));
|
||||
goto end;
|
||||
|
||||
free_memory:
|
||||
|
||||
@@ -70,20 +70,6 @@ void unregister_memory_notifier(struct notifier_block *nb)
|
||||
}
|
||||
EXPORT_SYMBOL(unregister_memory_notifier);
|
||||
|
||||
static ATOMIC_NOTIFIER_HEAD(memory_isolate_chain);
|
||||
|
||||
int register_memory_isolate_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_register(&memory_isolate_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(register_memory_isolate_notifier);
|
||||
|
||||
void unregister_memory_isolate_notifier(struct notifier_block *nb)
|
||||
{
|
||||
atomic_notifier_chain_unregister(&memory_isolate_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL(unregister_memory_isolate_notifier);
|
||||
|
||||
static void memory_block_release(struct device *dev)
|
||||
{
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
@@ -175,11 +161,6 @@ int memory_notify(unsigned long val, void *v)
|
||||
return blocking_notifier_call_chain(&memory_chain, val, v);
|
||||
}
|
||||
|
||||
int memory_isolate_notify(unsigned long val, void *v)
|
||||
{
|
||||
return atomic_notifier_call_chain(&memory_isolate_chain, val, v);
|
||||
}
|
||||
|
||||
/*
|
||||
* The probe routines leave the pages uninitialized, just as the bootmem code
|
||||
* does. Make sure we do not access them, but instead use only information from
|
||||
@@ -225,7 +206,7 @@ static bool pages_correctly_probed(unsigned long start_pfn)
|
||||
*/
|
||||
static int
|
||||
memory_block_action(unsigned long start_section_nr, unsigned long action,
|
||||
int online_type)
|
||||
int online_type, int nid)
|
||||
{
|
||||
unsigned long start_pfn;
|
||||
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
|
||||
@@ -238,7 +219,7 @@ memory_block_action(unsigned long start_section_nr, unsigned long action,
|
||||
if (!pages_correctly_probed(start_pfn))
|
||||
return -EBUSY;
|
||||
|
||||
ret = online_pages(start_pfn, nr_pages, online_type);
|
||||
ret = online_pages(start_pfn, nr_pages, online_type, nid);
|
||||
break;
|
||||
case MEM_OFFLINE:
|
||||
ret = offline_pages(start_pfn, nr_pages);
|
||||
@@ -264,7 +245,7 @@ static int memory_block_change_state(struct memory_block *mem,
|
||||
mem->state = MEM_GOING_OFFLINE;
|
||||
|
||||
ret = memory_block_action(mem->start_section_nr, to_state,
|
||||
mem->online_type);
|
||||
mem->online_type, mem->nid);
|
||||
|
||||
mem->state = ret ? from_state_req : to_state;
|
||||
|
||||
|
||||
@@ -207,14 +207,17 @@ static inline void zram_fill_page(void *ptr, unsigned long len,
|
||||
|
||||
static bool page_same_filled(void *ptr, unsigned long *element)
|
||||
{
|
||||
unsigned int pos;
|
||||
unsigned long *page;
|
||||
unsigned long val;
|
||||
unsigned int pos, last_pos = PAGE_SIZE / sizeof(*page) - 1;
|
||||
|
||||
page = (unsigned long *)ptr;
|
||||
val = page[0];
|
||||
|
||||
for (pos = 1; pos < PAGE_SIZE / sizeof(*page); pos++) {
|
||||
if (val != page[last_pos])
|
||||
return false;
|
||||
|
||||
for (pos = 1; pos < last_pos; pos++) {
|
||||
if (val != page[pos])
|
||||
return false;
|
||||
}
|
||||
@@ -626,7 +629,7 @@ static ssize_t writeback_store(struct device *dev,
|
||||
struct bio bio;
|
||||
struct bio_vec bio_vec;
|
||||
struct page *page;
|
||||
ssize_t ret;
|
||||
ssize_t ret = len;
|
||||
int mode;
|
||||
unsigned long blk_idx = 0;
|
||||
|
||||
@@ -762,7 +765,6 @@ next:
|
||||
|
||||
if (blk_idx)
|
||||
free_block_bdev(zram, blk_idx);
|
||||
ret = len;
|
||||
__free_page(page);
|
||||
release_init_lock:
|
||||
up_read(&zram->init_lock);
|
||||
|
||||
@@ -188,8 +188,8 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
|
||||
kfree(vsg->desc_pages);
|
||||
/* fall through */
|
||||
case dr_via_pages_locked:
|
||||
put_user_pages_dirty_lock(vsg->pages, vsg->num_pages,
|
||||
(vsg->direction == DMA_FROM_DEVICE));
|
||||
unpin_user_pages_dirty_lock(vsg->pages, vsg->num_pages,
|
||||
(vsg->direction == DMA_FROM_DEVICE));
|
||||
/* fall through */
|
||||
case dr_via_pages_alloc:
|
||||
vfree(vsg->pages);
|
||||
@@ -239,7 +239,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
|
||||
vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages));
|
||||
if (NULL == vsg->pages)
|
||||
return -ENOMEM;
|
||||
ret = get_user_pages_fast((unsigned long)xfer->mem_addr,
|
||||
ret = pin_user_pages_fast((unsigned long)xfer->mem_addr,
|
||||
vsg->num_pages,
|
||||
vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
|
||||
vsg->pages);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/log2.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#include "qcom-vadc-common.h"
|
||||
|
||||
@@ -236,8 +237,7 @@ static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph,
|
||||
voltage = 0;
|
||||
}
|
||||
|
||||
voltage -= KELVINMIL_CELSIUSMIL;
|
||||
*result_mdec = voltage;
|
||||
*result_mdec = milli_kelvin_to_millicelsius(voltage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ static int qcom_vadc_scale_hw_calib_die_temp(
|
||||
{
|
||||
*result_mdec = qcom_vadc_scale_code_voltage_factor(adc_code,
|
||||
prescale, data, 2);
|
||||
*result_mdec -= KELVINMIL_CELSIUSMIL;
|
||||
*result_mdec = milli_kelvin_to_millicelsius(*result_mdec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#define VADC_AVG_SAMPLES_MAX 512
|
||||
#define ADC5_AVG_SAMPLES_MAX 16
|
||||
|
||||
#define KELVINMIL_CELSIUSMIL 273150
|
||||
#define PMIC5_CHG_TEMP_SCALE_FACTOR 377500
|
||||
#define PMIC5_SMB_TEMP_CONSTANT 419400
|
||||
#define PMIC5_SMB_TEMP_SCALE_FACTOR 356
|
||||
|
||||
@@ -54,7 +54,7 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
|
||||
|
||||
for_each_sg_page(umem->sg_head.sgl, &sg_iter, umem->sg_nents, 0) {
|
||||
page = sg_page_iter_page(&sg_iter);
|
||||
put_user_pages_dirty_lock(&page, 1, umem->writable && dirty);
|
||||
unpin_user_pages_dirty_lock(&page, 1, umem->writable && dirty);
|
||||
}
|
||||
|
||||
sg_free_table(&umem->sg_head);
|
||||
@@ -257,16 +257,13 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
|
||||
sg = umem->sg_head.sgl;
|
||||
|
||||
while (npages) {
|
||||
down_read(&mm->mmap_sem);
|
||||
ret = get_user_pages(cur_base,
|
||||
min_t(unsigned long, npages,
|
||||
PAGE_SIZE / sizeof (struct page *)),
|
||||
gup_flags | FOLL_LONGTERM,
|
||||
page_list, NULL);
|
||||
if (ret < 0) {
|
||||
up_read(&mm->mmap_sem);
|
||||
ret = pin_user_pages_fast(cur_base,
|
||||
min_t(unsigned long, npages,
|
||||
PAGE_SIZE /
|
||||
sizeof(struct page *)),
|
||||
gup_flags | FOLL_LONGTERM, page_list);
|
||||
if (ret < 0)
|
||||
goto umem_release;
|
||||
}
|
||||
|
||||
cur_base += ret * PAGE_SIZE;
|
||||
npages -= ret;
|
||||
@@ -274,8 +271,6 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
|
||||
sg = ib_umem_add_sg_table(sg, page_list, ret,
|
||||
dma_get_max_seg_size(device->dma_device),
|
||||
&umem->sg_nents);
|
||||
|
||||
up_read(&mm->mmap_sem);
|
||||
}
|
||||
|
||||
sg_mark_end(sg);
|
||||
|
||||
@@ -293,9 +293,8 @@ EXPORT_SYMBOL(ib_umem_odp_release);
|
||||
* The function returns -EFAULT if the DMA mapping operation fails. It returns
|
||||
* -EAGAIN if a concurrent invalidation prevents us from updating the page.
|
||||
*
|
||||
* The page is released via put_user_page even if the operation failed. For
|
||||
* on-demand pinning, the page is released whenever it isn't stored in the
|
||||
* umem.
|
||||
* The page is released via put_page even if the operation failed. For on-demand
|
||||
* pinning, the page is released whenever it isn't stored in the umem.
|
||||
*/
|
||||
static int ib_umem_odp_map_dma_single_page(
|
||||
struct ib_umem_odp *umem_odp,
|
||||
@@ -348,7 +347,7 @@ static int ib_umem_odp_map_dma_single_page(
|
||||
}
|
||||
|
||||
out:
|
||||
put_user_page(page);
|
||||
put_page(page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -458,7 +457,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, u64 user_virt,
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
put_user_page(local_page_list[j]);
|
||||
put_page(local_page_list[j]);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -485,8 +484,8 @@ int ib_umem_odp_map_dma_pages(struct ib_umem_odp *umem_odp, u64 user_virt,
|
||||
* ib_umem_odp_map_dma_single_page().
|
||||
*/
|
||||
if (npages - (j + 1) > 0)
|
||||
put_user_pages(&local_page_list[j+1],
|
||||
npages - (j + 1));
|
||||
release_pages(&local_page_list[j+1],
|
||||
npages - (j + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np
|
||||
int ret;
|
||||
unsigned int gup_flags = FOLL_LONGTERM | (writable ? FOLL_WRITE : 0);
|
||||
|
||||
ret = get_user_pages_fast(vaddr, npages, gup_flags, pages);
|
||||
ret = pin_user_pages_fast(vaddr, npages, gup_flags, pages);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -118,7 +118,7 @@ int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t np
|
||||
void hfi1_release_user_pages(struct mm_struct *mm, struct page **p,
|
||||
size_t npages, bool dirty)
|
||||
{
|
||||
put_user_pages_dirty_lock(p, npages, dirty);
|
||||
unpin_user_pages_dirty_lock(p, npages, dirty);
|
||||
|
||||
if (mm) { /* during close after signal, mm can be NULL */
|
||||
atomic64_sub(npages, &mm->pinned_vm);
|
||||
|
||||
@@ -472,7 +472,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = get_user_pages_fast(uaddr & PAGE_MASK, 1,
|
||||
ret = pin_user_pages_fast(uaddr & PAGE_MASK, 1,
|
||||
FOLL_WRITE | FOLL_LONGTERM, pages);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@@ -482,7 +482,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
|
||||
|
||||
ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
|
||||
if (ret < 0) {
|
||||
put_user_page(pages[0]);
|
||||
unpin_user_page(pages[0]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
|
||||
mthca_uarc_virt(dev, uar, i));
|
||||
if (ret) {
|
||||
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
|
||||
put_user_page(sg_page(&db_tab->page[i].mem));
|
||||
unpin_user_page(sg_page(&db_tab->page[i].mem));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -556,7 +556,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
|
||||
if (db_tab->page[i].uvirt) {
|
||||
mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1);
|
||||
pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
|
||||
put_user_page(sg_page(&db_tab->page[i].mem));
|
||||
unpin_user_page(sg_page(&db_tab->page[i].mem));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
static void __qib_release_user_pages(struct page **p, size_t num_pages,
|
||||
int dirty)
|
||||
{
|
||||
put_user_pages_dirty_lock(p, num_pages, dirty);
|
||||
unpin_user_pages_dirty_lock(p, num_pages, dirty);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +108,7 @@ int qib_get_user_pages(unsigned long start_page, size_t num_pages,
|
||||
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
for (got = 0; got < num_pages; got += ret) {
|
||||
ret = get_user_pages(start_page + got * PAGE_SIZE,
|
||||
ret = pin_user_pages(start_page + got * PAGE_SIZE,
|
||||
num_pages - got,
|
||||
FOLL_LONGTERM | FOLL_WRITE | FOLL_FORCE,
|
||||
p + got, NULL);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user