Merge commit 'db0b2e84b55dcf35e9fa8c25aa46061c1b1db927' into HEAD
Change-Id: Ie538607f2cdc24cb722105fced4d1a40028efd57 Signed-off-by: Pradosh Das <prados@codeaurora.org>
This commit is contained in:
commit
abce7ac781
236 changed files with 17246 additions and 2372 deletions
|
@ -1,119 +0,0 @@
|
|||
What: /sys/block/zram<id>/num_reads
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The num_reads file is read-only and specifies the number of
|
||||
reads (failed or successful) done on this device.
|
||||
Now accessible via zram<id>/stat node.
|
||||
|
||||
What: /sys/block/zram<id>/num_writes
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The num_writes file is read-only and specifies the number of
|
||||
writes (failed or successful) done on this device.
|
||||
Now accessible via zram<id>/stat node.
|
||||
|
||||
What: /sys/block/zram<id>/invalid_io
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The invalid_io file is read-only and specifies the number of
|
||||
non-page-size-aligned I/O requests issued to this device.
|
||||
Now accessible via zram<id>/io_stat node.
|
||||
|
||||
What: /sys/block/zram<id>/failed_reads
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The failed_reads file is read-only and specifies the number of
|
||||
failed reads happened on this device.
|
||||
Now accessible via zram<id>/io_stat node.
|
||||
|
||||
What: /sys/block/zram<id>/failed_writes
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The failed_writes file is read-only and specifies the number of
|
||||
failed writes happened on this device.
|
||||
Now accessible via zram<id>/io_stat node.
|
||||
|
||||
What: /sys/block/zram<id>/notify_free
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The notify_free file is read-only. Depending on device usage
|
||||
scenario it may account a) the number of pages freed because
|
||||
of swap slot free notifications or b) the number of pages freed
|
||||
because of REQ_DISCARD requests sent by bio. The former ones
|
||||
are sent to a swap block device when a swap slot is freed, which
|
||||
implies that this disk is being used as a swap disk. The latter
|
||||
ones are sent by filesystem mounted with discard option,
|
||||
whenever some data blocks are getting discarded.
|
||||
Now accessible via zram<id>/io_stat node.
|
||||
|
||||
What: /sys/block/zram<id>/zero_pages
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The zero_pages file is read-only and specifies number of zero
|
||||
filled pages written to this disk. No memory is allocated for
|
||||
such pages.
|
||||
Now accessible via zram<id>/mm_stat node.
|
||||
|
||||
What: /sys/block/zram<id>/orig_data_size
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The orig_data_size file is read-only and specifies uncompressed
|
||||
size of data stored in this disk. This excludes zero-filled
|
||||
pages (zero_pages) since no memory is allocated for them.
|
||||
Unit: bytes
|
||||
Now accessible via zram<id>/mm_stat node.
|
||||
|
||||
What: /sys/block/zram<id>/compr_data_size
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The compr_data_size file is read-only and specifies compressed
|
||||
size of data stored in this disk. So, compression ratio can be
|
||||
calculated using orig_data_size and this statistic.
|
||||
Unit: bytes
|
||||
Now accessible via zram<id>/mm_stat node.
|
||||
|
||||
What: /sys/block/zram<id>/mem_used_total
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The mem_used_total file is read-only and specifies the amount
|
||||
of memory, including allocator fragmentation and metadata
|
||||
overhead, allocated for this disk. So, allocator space
|
||||
efficiency can be calculated using compr_data_size and this
|
||||
statistic.
|
||||
Unit: bytes
|
||||
Now accessible via zram<id>/mm_stat node.
|
||||
|
||||
What: /sys/block/zram<id>/mem_used_max
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The mem_used_max file is read/write and specifies the amount
|
||||
of maximum memory zram have consumed to store compressed data.
|
||||
For resetting the value, you should write "0". Otherwise,
|
||||
you could see -EINVAL.
|
||||
Unit: bytes
|
||||
Downgraded to write-only node: so it's possible to set new
|
||||
value only; its current value is stored in zram<id>/mm_stat
|
||||
node.
|
||||
|
||||
What: /sys/block/zram<id>/mem_limit
|
||||
Date: August 2015
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The mem_limit file is read/write and specifies the maximum
|
||||
amount of memory ZRAM can use to store the compressed data.
|
||||
The limit could be changed in run time and "0" means disable
|
||||
the limit. No limit is the initial state. Unit: bytes
|
||||
Downgraded to write-only node: so it's possible to set new
|
||||
value only; its current value is stored in zram<id>/mm_stat
|
||||
node.
|
|
@ -22,41 +22,6 @@ Description:
|
|||
device. The reset operation frees all the memory associated
|
||||
with this device.
|
||||
|
||||
What: /sys/block/zram<id>/num_reads
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The num_reads file is read-only and specifies the number of
|
||||
reads (failed or successful) done on this device.
|
||||
|
||||
What: /sys/block/zram<id>/num_writes
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The num_writes file is read-only and specifies the number of
|
||||
writes (failed or successful) done on this device.
|
||||
|
||||
What: /sys/block/zram<id>/invalid_io
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The invalid_io file is read-only and specifies the number of
|
||||
non-page-size-aligned I/O requests issued to this device.
|
||||
|
||||
What: /sys/block/zram<id>/failed_reads
|
||||
Date: February 2014
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The failed_reads file is read-only and specifies the number of
|
||||
failed reads happened on this device.
|
||||
|
||||
What: /sys/block/zram<id>/failed_writes
|
||||
Date: February 2014
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The failed_writes file is read-only and specifies the number of
|
||||
failed writes happened on this device.
|
||||
|
||||
What: /sys/block/zram<id>/max_comp_streams
|
||||
Date: February 2014
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
|
@ -73,74 +38,24 @@ Description:
|
|||
available and selected compression algorithms, change
|
||||
compression algorithm selection.
|
||||
|
||||
What: /sys/block/zram<id>/notify_free
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The notify_free file is read-only. Depending on device usage
|
||||
scenario it may account a) the number of pages freed because
|
||||
of swap slot free notifications or b) the number of pages freed
|
||||
because of REQ_DISCARD requests sent by bio. The former ones
|
||||
are sent to a swap block device when a swap slot is freed, which
|
||||
implies that this disk is being used as a swap disk. The latter
|
||||
ones are sent by filesystem mounted with discard option,
|
||||
whenever some data blocks are getting discarded.
|
||||
|
||||
What: /sys/block/zram<id>/zero_pages
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The zero_pages file is read-only and specifies number of zero
|
||||
filled pages written to this disk. No memory is allocated for
|
||||
such pages.
|
||||
|
||||
What: /sys/block/zram<id>/orig_data_size
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The orig_data_size file is read-only and specifies uncompressed
|
||||
size of data stored in this disk. This excludes zero-filled
|
||||
pages (zero_pages) since no memory is allocated for them.
|
||||
Unit: bytes
|
||||
|
||||
What: /sys/block/zram<id>/compr_data_size
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The compr_data_size file is read-only and specifies compressed
|
||||
size of data stored in this disk. So, compression ratio can be
|
||||
calculated using orig_data_size and this statistic.
|
||||
Unit: bytes
|
||||
|
||||
What: /sys/block/zram<id>/mem_used_total
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The mem_used_total file is read-only and specifies the amount
|
||||
of memory, including allocator fragmentation and metadata
|
||||
overhead, allocated for this disk. So, allocator space
|
||||
efficiency can be calculated using compr_data_size and this
|
||||
statistic.
|
||||
Unit: bytes
|
||||
|
||||
What: /sys/block/zram<id>/mem_used_max
|
||||
Date: August 2014
|
||||
Contact: Minchan Kim <minchan@kernel.org>
|
||||
Description:
|
||||
The mem_used_max file is read/write and specifies the amount
|
||||
of maximum memory zram have consumed to store compressed data.
|
||||
For resetting the value, you should write "0". Otherwise,
|
||||
you could see -EINVAL.
|
||||
The mem_used_max file is write-only and is used to reset
|
||||
the counter of maximum memory zram have consumed to store
|
||||
compressed data. For resetting the value, you should write
|
||||
"0". Otherwise, you could see -EINVAL.
|
||||
Unit: bytes
|
||||
|
||||
What: /sys/block/zram<id>/mem_limit
|
||||
Date: August 2014
|
||||
Contact: Minchan Kim <minchan@kernel.org>
|
||||
Description:
|
||||
The mem_limit file is read/write and specifies the maximum
|
||||
amount of memory ZRAM can use to store the compressed data. The
|
||||
limit could be changed in run time and "0" means disable the
|
||||
limit. No limit is the initial state. Unit: bytes
|
||||
The mem_limit file is write-only and specifies the maximum
|
||||
amount of memory ZRAM can use to store the compressed data.
|
||||
The limit could be changed in run time and "0" means disable
|
||||
the limit. No limit is the initial state. Unit: bytes
|
||||
|
||||
What: /sys/block/zram<id>/compact
|
||||
Date: August 2015
|
||||
|
@ -166,3 +81,20 @@ Description:
|
|||
The mm_stat file is read-only and represents device's mm
|
||||
statistics (orig_data_size, compr_data_size, etc.) in a format
|
||||
similar to block layer statistics file format.
|
||||
|
||||
What: /sys/block/zram<id>/debug_stat
|
||||
Date: July 2016
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The debug_stat file is read-only and represents various
|
||||
device's debugging info useful for kernel developers. Its
|
||||
format is not documented intentionally and may change
|
||||
anytime without any notice.
|
||||
|
||||
What: /sys/block/zram<id>/backing_dev
|
||||
Date: June 2017
|
||||
Contact: Minchan Kim <minchan@kernel.org>
|
||||
Description:
|
||||
The backing_dev file is read-write and set up backing
|
||||
device for zram to write incompressible pages.
|
||||
For using, user should enable CONFIG_ZRAM_WRITEBACK.
|
||||
|
|
|
@ -25,7 +25,7 @@ o GNU C 3.2 # gcc --version
|
|||
o GNU make 3.80 # make --version
|
||||
o binutils 2.12 # ld -v
|
||||
o util-linux 2.10o # fdformat --version
|
||||
o module-init-tools 0.9.10 # depmod -V
|
||||
o kmod 13 # depmod -V
|
||||
o e2fsprogs 1.41.4 # e2fsck -V
|
||||
o jfsutils 1.1.3 # fsck.jfs -V
|
||||
o reiserfsprogs 3.6.3 # reiserfsck -V
|
||||
|
@ -132,12 +132,6 @@ is not build with CONFIG_KALLSYMS and you have no way to rebuild and
|
|||
reproduce the Oops with that option, then you can still decode that Oops
|
||||
with ksymoops.
|
||||
|
||||
Module-Init-Tools
|
||||
-----------------
|
||||
|
||||
A new module loader is now in the kernel that requires module-init-tools
|
||||
to use. It is backward compatible with the 2.4.x series kernels.
|
||||
|
||||
Mkinitrd
|
||||
--------
|
||||
|
||||
|
@ -319,14 +313,15 @@ Util-linux
|
|||
----------
|
||||
o <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>
|
||||
|
||||
Kmod
|
||||
----
|
||||
o <https://www.kernel.org/pub/linux/utils/kernel/kmod/>
|
||||
o <https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git>
|
||||
|
||||
Ksymoops
|
||||
--------
|
||||
o <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
|
||||
|
||||
Module-Init-Tools
|
||||
-----------------
|
||||
o <ftp://ftp.kernel.org/pub/linux/kernel/people/rusty/modules/>
|
||||
|
||||
Mkinitrd
|
||||
--------
|
||||
o <https://code.launchpad.net/initrd-tools/main>
|
||||
|
|
|
@ -59,34 +59,23 @@ num_devices parameter is optional and tells zram how many devices should be
|
|||
pre-created. Default: 1.
|
||||
|
||||
2) Set max number of compression streams
|
||||
Compression backend may use up to max_comp_streams compression streams,
|
||||
thus allowing up to max_comp_streams concurrent compression operations.
|
||||
By default, compression backend uses single compression stream.
|
||||
Regardless the value passed to this attribute, ZRAM will always
|
||||
allocate multiple compression streams - one per online CPUs - thus
|
||||
allowing several concurrent compression operations. The number of
|
||||
allocated compression streams goes down when some of the CPUs
|
||||
become offline. There is no single-compression-stream mode anymore,
|
||||
unless you are running a UP system or has only 1 CPU online.
|
||||
|
||||
Examples:
|
||||
#show max compression streams number
|
||||
To find out how many streams are currently available:
|
||||
cat /sys/block/zram0/max_comp_streams
|
||||
|
||||
#set max compression streams number to 3
|
||||
echo 3 > /sys/block/zram0/max_comp_streams
|
||||
|
||||
Note:
|
||||
In order to enable compression backend's multi stream support max_comp_streams
|
||||
must be initially set to desired concurrency level before ZRAM device
|
||||
initialisation. Once the device initialised as a single stream compression
|
||||
backend (max_comp_streams equals to 1), you will see error if you try to change
|
||||
the value of max_comp_streams because single stream compression backend
|
||||
implemented as a special case by lock overhead issue and does not support
|
||||
dynamic max_comp_streams. Only multi stream backend supports dynamic
|
||||
max_comp_streams adjustment.
|
||||
|
||||
3) Select compression algorithm
|
||||
Using comp_algorithm device attribute one can see available and
|
||||
currently selected (shown in square brackets) compression algorithms,
|
||||
change selected compression algorithm (once the device is initialised
|
||||
there is no way to change compression algorithm).
|
||||
Using comp_algorithm device attribute one can see available and
|
||||
currently selected (shown in square brackets) compression algorithms,
|
||||
change selected compression algorithm (once the device is initialised
|
||||
there is no way to change compression algorithm).
|
||||
|
||||
Examples:
|
||||
Examples:
|
||||
#show supported compression algorithms
|
||||
cat /sys/block/zram0/comp_algorithm
|
||||
lzo [lz4]
|
||||
|
@ -94,17 +83,27 @@ max_comp_streams adjustment.
|
|||
#select lzo compression algorithm
|
||||
echo lzo > /sys/block/zram0/comp_algorithm
|
||||
|
||||
4) Set Disksize
|
||||
Set disk size by writing the value to sysfs node 'disksize'.
|
||||
The value can be either in bytes or you can use mem suffixes.
|
||||
Examples:
|
||||
# Initialize /dev/zram0 with 50MB disksize
|
||||
echo $((50*1024*1024)) > /sys/block/zram0/disksize
|
||||
For the time being, the `comp_algorithm' content does not necessarily
|
||||
show every compression algorithm supported by the kernel. We keep this
|
||||
list primarily to simplify device configuration and one can configure
|
||||
a new device with a compression algorithm that is not listed in
|
||||
`comp_algorithm'. The thing is that, internally, ZRAM uses Crypto API
|
||||
and, if some of the algorithms were built as modules, it's impossible
|
||||
to list all of them using, for instance, /proc/crypto or any other
|
||||
method. This, however, has an advantage of permitting the usage of
|
||||
custom crypto compression modules (implementing S/W or H/W compression).
|
||||
|
||||
# Using mem suffixes
|
||||
echo 256K > /sys/block/zram0/disksize
|
||||
echo 512M > /sys/block/zram0/disksize
|
||||
echo 1G > /sys/block/zram0/disksize
|
||||
4) Set Disksize
|
||||
Set disk size by writing the value to sysfs node 'disksize'.
|
||||
The value can be either in bytes or you can use mem suffixes.
|
||||
Examples:
|
||||
# Initialize /dev/zram0 with 50MB disksize
|
||||
echo $((50*1024*1024)) > /sys/block/zram0/disksize
|
||||
|
||||
# Using mem suffixes
|
||||
echo 256K > /sys/block/zram0/disksize
|
||||
echo 512M > /sys/block/zram0/disksize
|
||||
echo 1G > /sys/block/zram0/disksize
|
||||
|
||||
Note:
|
||||
There is little point creating a zram of greater than twice the size of memory
|
||||
|
@ -112,20 +111,20 @@ since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the
|
|||
size of the disk when not in use so a huge zram is wasteful.
|
||||
|
||||
5) Set memory limit: Optional
|
||||
Set memory limit by writing the value to sysfs node 'mem_limit'.
|
||||
The value can be either in bytes or you can use mem suffixes.
|
||||
In addition, you could change the value in runtime.
|
||||
Examples:
|
||||
# limit /dev/zram0 with 50MB memory
|
||||
echo $((50*1024*1024)) > /sys/block/zram0/mem_limit
|
||||
Set memory limit by writing the value to sysfs node 'mem_limit'.
|
||||
The value can be either in bytes or you can use mem suffixes.
|
||||
In addition, you could change the value in runtime.
|
||||
Examples:
|
||||
# limit /dev/zram0 with 50MB memory
|
||||
echo $((50*1024*1024)) > /sys/block/zram0/mem_limit
|
||||
|
||||
# Using mem suffixes
|
||||
echo 256K > /sys/block/zram0/mem_limit
|
||||
echo 512M > /sys/block/zram0/mem_limit
|
||||
echo 1G > /sys/block/zram0/mem_limit
|
||||
# Using mem suffixes
|
||||
echo 256K > /sys/block/zram0/mem_limit
|
||||
echo 512M > /sys/block/zram0/mem_limit
|
||||
echo 1G > /sys/block/zram0/mem_limit
|
||||
|
||||
# To disable memory limit
|
||||
echo 0 > /sys/block/zram0/mem_limit
|
||||
# To disable memory limit
|
||||
echo 0 > /sys/block/zram0/mem_limit
|
||||
|
||||
6) Activate:
|
||||
mkswap /dev/zram0
|
||||
|
@ -162,41 +161,15 @@ Name access description
|
|||
disksize RW show and set the device's disk size
|
||||
initstate RO shows the initialization state of the device
|
||||
reset WO trigger device reset
|
||||
num_reads RO the number of reads
|
||||
failed_reads RO the number of failed reads
|
||||
num_write RO the number of writes
|
||||
failed_writes RO the number of failed writes
|
||||
invalid_io RO the number of non-page-size-aligned I/O requests
|
||||
mem_used_max WO reset the `mem_used_max' counter (see later)
|
||||
mem_limit WO specifies the maximum amount of memory ZRAM can use
|
||||
to store the compressed data
|
||||
max_comp_streams RW the number of possible concurrent compress operations
|
||||
comp_algorithm RW show and change the compression algorithm
|
||||
notify_free RO the number of notifications to free pages (either
|
||||
slot free notifications or REQ_DISCARD requests)
|
||||
zero_pages RO the number of zero filled pages written to this disk
|
||||
orig_data_size RO uncompressed size of data stored in this disk
|
||||
compr_data_size RO compressed size of data stored in this disk
|
||||
mem_used_total RO the amount of memory allocated for this disk
|
||||
mem_used_max RW the maximum amount of memory zram have consumed to
|
||||
store the data (to reset this counter to the actual
|
||||
current value, write 1 to this attribute)
|
||||
mem_limit RW the maximum amount of memory ZRAM can use to store
|
||||
the compressed data
|
||||
pages_compacted RO the number of pages freed during compaction
|
||||
(available only via zram<id>/mm_stat node)
|
||||
compact WO trigger memory compaction
|
||||
debug_stat RO this file is used for zram debugging purposes
|
||||
backing_dev RW set up backend storage for zram to write out
|
||||
|
||||
WARNING
|
||||
=======
|
||||
per-stat sysfs attributes are considered to be deprecated.
|
||||
The basic strategy is:
|
||||
-- the existing RW nodes will be downgraded to WO nodes (in linux 4.11)
|
||||
-- deprecated RO sysfs nodes will eventually be removed (in linux 4.11)
|
||||
|
||||
The list of deprecated attributes can be found here:
|
||||
Documentation/ABI/obsolete/sysfs-block-zram
|
||||
|
||||
Basically, every attribute that has its own read accessible sysfs node
|
||||
(e.g. num_reads) *AND* is accessible via one of the stat files (zram<id>/stat
|
||||
or zram<id>/io_stat or zram<id>/mm_stat) is considered to be deprecated.
|
||||
|
||||
User space is advised to use the following files to read the device statistics.
|
||||
|
||||
|
@ -211,22 +184,41 @@ The stat file represents device's I/O statistics not accounted by block
|
|||
layer and, thus, not available in zram<id>/stat file. It consists of a
|
||||
single line of text and contains the following stats separated by
|
||||
whitespace:
|
||||
failed_reads
|
||||
failed_writes
|
||||
invalid_io
|
||||
notify_free
|
||||
failed_reads the number of failed reads
|
||||
failed_writes the number of failed writes
|
||||
invalid_io the number of non-page-size-aligned I/O requests
|
||||
notify_free Depending on device usage scenario it may account
|
||||
a) the number of pages freed because of swap slot free
|
||||
notifications or b) the number of pages freed because of
|
||||
REQ_DISCARD requests sent by bio. The former ones are
|
||||
sent to a swap block device when a swap slot is freed,
|
||||
which implies that this disk is being used as a swap disk.
|
||||
The latter ones are sent by filesystem mounted with
|
||||
discard option, whenever some data blocks are getting
|
||||
discarded.
|
||||
|
||||
File /sys/block/zram<id>/mm_stat
|
||||
|
||||
The stat file represents device's mm statistics. It consists of a single
|
||||
line of text and contains the following stats separated by whitespace:
|
||||
orig_data_size
|
||||
compr_data_size
|
||||
mem_used_total
|
||||
mem_limit
|
||||
mem_used_max
|
||||
zero_pages
|
||||
num_migrated
|
||||
orig_data_size uncompressed size of data stored in this disk.
|
||||
This excludes same-element-filled pages (same_pages) since
|
||||
no memory is allocated for them.
|
||||
Unit: bytes
|
||||
compr_data_size compressed size of data stored in this disk
|
||||
mem_used_total the amount of memory allocated for this disk. This
|
||||
includes allocator fragmentation and metadata overhead,
|
||||
allocated for this disk. So, allocator space efficiency
|
||||
can be calculated using compr_data_size and this statistic.
|
||||
Unit: bytes
|
||||
mem_limit the maximum amount of memory ZRAM can use to store
|
||||
the compressed data
|
||||
mem_used_max the maximum amount of memory zram have consumed to
|
||||
store the data
|
||||
same_pages the number of same element filled pages written to this disk.
|
||||
No memory is allocated for such pages.
|
||||
pages_compacted the number of pages freed during compaction
|
||||
huge_pages the number of incompressible pages
|
||||
|
||||
9) Deactivate:
|
||||
swapoff /dev/zram0
|
||||
|
@ -241,5 +233,39 @@ line of text and contains the following stats separated by whitespace:
|
|||
resets the disksize to zero. You must set the disksize again
|
||||
before reusing the device.
|
||||
|
||||
* Optional Feature
|
||||
|
||||
= writeback
|
||||
|
||||
With incompressible pages, there is no memory saving with zram.
|
||||
Instead, with CONFIG_ZRAM_WRITEBACK, zram can write incompressible page
|
||||
to backing storage rather than keeping it in memory.
|
||||
User should set up backing device via /sys/block/zramX/backing_dev
|
||||
before disksize setting.
|
||||
|
||||
= memory tracking
|
||||
|
||||
With CONFIG_ZRAM_MEMORY_TRACKING, user can know information of the
|
||||
zram block. It could be useful to catch cold or incompressible
|
||||
pages of the process with*pagemap.
|
||||
If you enable the feature, you could see block state via
|
||||
/sys/kernel/debug/zram/zram0/block_state". The output is as follows,
|
||||
|
||||
300 75.033841 .wh
|
||||
301 63.806904 s..
|
||||
302 63.806919 ..h
|
||||
|
||||
First column is zram's block index.
|
||||
Second column is access time since the system was booted
|
||||
Third column is state of the block.
|
||||
(s: same page
|
||||
w: written page to backing store
|
||||
h: huge page)
|
||||
|
||||
First line of above example says 300th block is accessed at 75.033841sec
|
||||
and the block's state is huge so it is written back to the backing
|
||||
storage. It's a debugging feature so anyone shouldn't rely on it to work
|
||||
properly.
|
||||
|
||||
Nitin Gupta
|
||||
ngupta@vflare.org
|
||||
|
|
|
@ -95,6 +95,9 @@ SoCs:
|
|||
- SDM660
|
||||
compatible = "qcom,sdm660"
|
||||
|
||||
- SDM455
|
||||
compatible = "qcom,sdm455"
|
||||
|
||||
- SDA658
|
||||
compatible = "qcom,sda658"
|
||||
|
||||
|
@ -292,6 +295,9 @@ compatible = "qcom,sdm660-cdp"
|
|||
compatible = "qcom,sdm660-mtp"
|
||||
compatible = "qcom,sdm660-qrd"
|
||||
compatible = "qcom,sda660-qrd"
|
||||
compatible = "qcom,sdm455-mtp"
|
||||
compatible = "qcom,sdm455-qrd"
|
||||
compatible = "qcom,sdm455-cdp"
|
||||
compatible = "qcom,sda658-mtp"
|
||||
compatible = "qcom,sda658-cdp"
|
||||
compatible = "qcom,sda660-mtp"
|
||||
|
|
|
@ -13,7 +13,6 @@ Optional properties:
|
|||
- qcom,fastrpc-glink: Flag to use glink instead of smd for IPC
|
||||
- qcom,fastrpc-vmid-heap-shared: Flag for Dynamic heap feature, to
|
||||
share HLOS memory buffer to ADSP
|
||||
- qcom,secure-domains: FastRPC secure domain configuration
|
||||
|
||||
Optional subnodes:
|
||||
- qcom,msm_fastrpc_compute_cb : Child nodes representing the compute context
|
||||
|
|
6
Makefile
6
Makefile
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 148
|
||||
SUBLEVEL = 153
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
@ -425,7 +425,9 @@ export MAKE AWK GENKSYMS INSTALLKERNEL PERL PYTHON UTS_MACHINE
|
|||
export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
|
||||
|
||||
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
|
||||
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV CFLAGS_KCOV CFLAGS_KASAN CFLAGS_UBSAN
|
||||
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV
|
||||
export CFLAGS_KASAN CFLAGS_UBSAN CFLAGS_KASAN_NOSANITIZE
|
||||
export CFLAGS_KCOV
|
||||
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
||||
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
|
||||
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
|
||||
|
|
|
@ -14,7 +14,7 @@ endif
|
|||
|
||||
KBUILD_DEFCONFIG := nsim_700_defconfig
|
||||
|
||||
cflags-y += -fno-common -pipe -fno-builtin -D__linux__
|
||||
cflags-y += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__
|
||||
cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7
|
||||
cflags-$(CONFIG_ISA_ARCV2) += -mcpu=archs
|
||||
|
||||
|
@ -137,16 +137,3 @@ dtbs: scripts
|
|||
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
|
||||
# Hacks to enable final link due to absence of link-time branch relexation
|
||||
# and gcc choosing optimal(shorter) branches at -O3
|
||||
#
|
||||
# vineetg Feb 2010: -mlong-calls switched off for overall kernel build
|
||||
# However lib/decompress_inflate.o (.init.text) calls
|
||||
# zlib_inflate_workspacesize (.text) causing relocation errors.
|
||||
# Thus forcing all exten calls in this file to be long calls
|
||||
export CFLAGS_decompress_inflate.o = -mmedium-calls
|
||||
export CFLAGS_initramfs.o = -mmedium-calls
|
||||
ifdef CONFIG_SMP
|
||||
export CFLAGS_core.o = -mmedium-calls
|
||||
endif
|
||||
|
|
|
@ -34,9 +34,7 @@ struct machine_desc {
|
|||
const char *name;
|
||||
const char **dt_compat;
|
||||
void (*init_early)(void);
|
||||
#ifdef CONFIG_SMP
|
||||
void (*init_per_cpu)(unsigned int);
|
||||
#endif
|
||||
void (*init_machine)(void);
|
||||
void (*init_late)(void);
|
||||
|
||||
|
|
|
@ -31,10 +31,10 @@ void __init init_IRQ(void)
|
|||
/* a SMP H/w block could do IPI IRQ request here */
|
||||
if (plat_smp_ops.init_per_cpu)
|
||||
plat_smp_ops.init_per_cpu(smp_processor_id());
|
||||
#endif
|
||||
|
||||
if (machine_desc->init_per_cpu)
|
||||
machine_desc->init_per_cpu(smp_processor_id());
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -74,6 +74,11 @@
|
|||
};
|
||||
};
|
||||
|
||||
/* Table Table 5-79 of the TRM shows 480ab000 is reserved */
|
||||
&usb_otg_hs {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&iva {
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -508,6 +508,8 @@
|
|||
|
||||
touchscreen-size-x = <480>;
|
||||
touchscreen-size-y = <272>;
|
||||
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
tlv320aic3106: tlv320aic3106@1b {
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
reg = <0x18008000 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
|
||||
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <100000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -138,7 +138,7 @@
|
|||
reg = <0x1800b000 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
|
||||
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-frequency = <100000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
@ -267,11 +267,7 @@
|
|||
compatible = "ti,dm6441-gpio";
|
||||
gpio-controller;
|
||||
reg = <0x226000 0x1000>;
|
||||
interrupts = <42 IRQ_TYPE_EDGE_BOTH
|
||||
43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH
|
||||
45 IRQ_TYPE_EDGE_BOTH 46 IRQ_TYPE_EDGE_BOTH
|
||||
47 IRQ_TYPE_EDGE_BOTH 48 IRQ_TYPE_EDGE_BOTH
|
||||
49 IRQ_TYPE_EDGE_BOTH 50 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupts = <42 43 44 45 46 47 48 49 50>;
|
||||
ti,ngpio = <144>;
|
||||
ti,davinci-gpio-unbanked = <0>;
|
||||
status = "disabled";
|
||||
|
|
|
@ -118,6 +118,7 @@ dtb-$(CONFIG_ARCH_MSM8996) += msm8996-v2-pmi8994-cdp.dtb \
|
|||
|
||||
dtb-$(CONFIG_MSM_GVM_QUIN) += vplatform-lfv-msm8996-telematics.dtb \
|
||||
vplatform-lfv-msm8996-ivi.dtb \
|
||||
vplatform-lfv-msm8996-ivi_8GB.dtb \
|
||||
vplatform-lfv-msm8996-baseline.dtb \
|
||||
vplatform-lfv-msm8996-ivi-la.dtb \
|
||||
vplatform-lfv-msm8996-ivi-lv-mt.dtb
|
||||
|
|
|
@ -531,7 +531,7 @@
|
|||
qcom,vin-sel = <2>; /* S4 1.8V */
|
||||
qcom,src-sel = <0>; /* Constant */
|
||||
qcom,master-en = <1>; /* Enable GPIO */
|
||||
qcom,invert = <1>; /* Output high */
|
||||
qcom,invert = <0>; /* Output low */
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -687,9 +687,9 @@
|
|||
regulator-max-microvolt = <8>;
|
||||
|
||||
qcom,cpr-fuse-corners = <3>;
|
||||
qcom,cpr-fuse-combos = <24>;
|
||||
qcom,cpr-speed-bins = <3>;
|
||||
qcom,cpr-speed-bin-corners = <8 8 8>;
|
||||
qcom,cpr-fuse-combos = <32>;
|
||||
qcom,cpr-speed-bins = <4>;
|
||||
qcom,cpr-speed-bin-corners = <8 8 8 8>;
|
||||
qcom,cpr-corners = <8>;
|
||||
qcom,cpr-corner-fmax-map = <2 4 8>;
|
||||
|
||||
|
@ -783,9 +783,9 @@
|
|||
regulator-max-microvolt = <11>;
|
||||
|
||||
qcom,cpr-fuse-corners = <5>;
|
||||
qcom,cpr-fuse-combos = <24>;
|
||||
qcom,cpr-speed-bins = <3>;
|
||||
qcom,cpr-speed-bin-corners = <10 10 11>;
|
||||
qcom,cpr-fuse-combos = <32>;
|
||||
qcom,cpr-speed-bins = <4>;
|
||||
qcom,cpr-speed-bin-corners = <10 10 11 10>;
|
||||
qcom,cpr-corners =
|
||||
/* Speed bin 0 */
|
||||
<10 10 10 10 10 10 10 10>,
|
||||
|
@ -794,7 +794,10 @@
|
|||
<10 10 10 10 10 10 10 10>,
|
||||
|
||||
/* Speed bin 2 */
|
||||
<11 11 11 11 11 11 11 11>;
|
||||
<11 11 11 11 11 11 11 11>,
|
||||
|
||||
/* Speed bin 3 */
|
||||
<10 10 10 10 10 10 10 10>;
|
||||
|
||||
qcom,cpr-corner-fmax-map =
|
||||
/* Speed bin 0 */
|
||||
|
@ -804,7 +807,10 @@
|
|||
<2 4 6 9 10>,
|
||||
|
||||
/* Speed bin 2 */
|
||||
<2 4 6 9 11>;
|
||||
<2 4 6 9 11>,
|
||||
|
||||
/* Speed bin 3 */
|
||||
<2 4 6 9 10>;
|
||||
|
||||
qcom,cpr-voltage-ceiling =
|
||||
/* Speed bin 0 */
|
||||
|
@ -820,7 +826,12 @@
|
|||
/* Speed bin 2 */
|
||||
<724000 724000 724000 788000
|
||||
868000 868000 988000 988000
|
||||
988000 1140000 1140000>;
|
||||
988000 1140000 1140000>,
|
||||
|
||||
/* Speed bin 3 */
|
||||
<724000 724000 724000 788000
|
||||
868000 868000 988000 988000
|
||||
988000 1068000>;
|
||||
|
||||
qcom,cpr-voltage-floor =
|
||||
/* Speed bin 0 */
|
||||
|
@ -836,7 +847,12 @@
|
|||
/* Speed bin 2 */
|
||||
<588000 588000 596000 652000
|
||||
712000 712000 744000 784000
|
||||
784000 844000 900000>;
|
||||
784000 844000 900000>,
|
||||
|
||||
/* Speed bin 3 */
|
||||
<588000 588000 596000 652000
|
||||
712000 712000 744000 784000
|
||||
784000 844000>;
|
||||
|
||||
qcom,corner-frequencies =
|
||||
/* Speed bin 0 */
|
||||
|
@ -855,7 +871,13 @@
|
|||
<300000000 787200000 1113600000
|
||||
1344000000 1516800000 1670400000
|
||||
1881600000 2016000000 2150400000
|
||||
2380800000 2515200000>;
|
||||
2380800000 2515200000>,
|
||||
|
||||
/* Speed bin 3 */
|
||||
<300000000 787200000 1113600000
|
||||
1344000000 1516800000 1670400000
|
||||
1881600000 2016000000 2150400000
|
||||
2208000000>;
|
||||
|
||||
qcom,allow-voltage-interpolation;
|
||||
qcom,allow-quotient-interpolation;
|
||||
|
@ -899,7 +921,12 @@
|
|||
/* Speed bin 2 */
|
||||
<40000 40000 40000 40000
|
||||
40000 40000 40000 66000
|
||||
66000 40000 40000>;
|
||||
66000 40000 40000>,
|
||||
|
||||
/* Speed bin 3 */
|
||||
<40000 40000 40000 40000
|
||||
40000 40000 40000 66000
|
||||
66000 40000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2101,6 +2101,7 @@
|
|||
qcom,qdsp6v62-1-5;
|
||||
memory-region = <&modem_fw_mem>;
|
||||
qcom,mem-protect-id = <0xF>;
|
||||
qcom,complete-ramdump;
|
||||
qcom,cx-ipeak-vote;
|
||||
|
||||
/* GPIO inputs from mss */
|
||||
|
|
153
arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-common.dtsi
Normal file
153
arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-common.dtsi
Normal file
|
@ -0,0 +1,153 @@
|
|||
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "skeleton64.dtsi"
|
||||
#include "vplatform-lfv-msm8996.dtsi"
|
||||
#include <dt-bindings/clock/msm-clocks-8996.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
&soc {
|
||||
qcom,msm-audio-ion-vm {
|
||||
compatible = "qcom,msm-audio-ion-vm";
|
||||
qcom,smmu-enabled;
|
||||
};
|
||||
|
||||
qcom,hab {
|
||||
compatible = "qcom,hab";
|
||||
vmid = <2>;
|
||||
|
||||
mmidgrp100: mmidgrp100 {
|
||||
grp-start-id = <100>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp200: mmidgrp200 {
|
||||
grp-start-id = <200>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp300: mmidgrp300 {
|
||||
grp-start-id = <300>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp400: mmidgrp400 {
|
||||
grp-start-id = <400>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp500: mmidgrp500 {
|
||||
grp-start-id = <500>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp600: mmidgrp600 {
|
||||
grp-start-id = <600>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp700: mmidgrp700 {
|
||||
grp-start-id = <700>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp800: mmidgrp800 {
|
||||
grp-start-id = <800>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp900: mmidgrp900 {
|
||||
grp-start-id = <900>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp1000: mmidgrp1000 {
|
||||
grp-start-id = <1000>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
qcom,cnss {
|
||||
compatible = "qcom,cnss";
|
||||
wlan-bootstrap-gpio = <&tlmm 46 0>;
|
||||
vdd-wlan-en-supply = <&wlan_en_vreg>;
|
||||
vdd-wlan-supply = <&rome_vreg>;
|
||||
vdd-wlan-io-supply = <&pm8994_s4>;
|
||||
vdd-wlan-xtal-supply = <&pm8994_l30>;
|
||||
vdd-wlan-core-supply = <&pm8994_s3>;
|
||||
wlan-ant-switch-supply = <&pm8994_l18_pin_ctrl>;
|
||||
qcom,wlan-en-vreg-support;
|
||||
qcom,notify-modem-status;
|
||||
pinctrl-names = "bootstrap_active", "bootstrap_sleep";
|
||||
pinctrl-0 = <&cnss_bootstrap_active>;
|
||||
pinctrl-1 = <&cnss_bootstrap_sleep>;
|
||||
|
||||
qcom,msm-bus,name = "msm-cnss";
|
||||
qcom,msm-bus,num-cases = <4>;
|
||||
qcom,msm-bus,num-paths = <1>;
|
||||
qcom,msm-bus,vectors-KBps =
|
||||
/* No vote */
|
||||
<45 512 0 0>,
|
||||
/* Up to 200 Mbps */
|
||||
<45 512 41421 1520000>,
|
||||
/* Up to 400 Mbps */
|
||||
<45 512 96650 1520000>,
|
||||
/* Up to 800 Mbps */
|
||||
<45 512 207108 14432000>;
|
||||
};
|
||||
|
||||
subsys_notif_virt: qcom,subsys_notif_virt@2D000000 {
|
||||
compatible = "qcom,subsys-notif-virt";
|
||||
reg = <0x2D000000 0x100>;
|
||||
reg-names = "vdev_base";
|
||||
adsp {
|
||||
subsys-name = "adsp";
|
||||
interrupts = <0 43 0>;
|
||||
interrupt-names = "state-irq";
|
||||
type = "virtual";
|
||||
offset = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#include "vplatform-lfv-msm8996-usb.dtsi"
|
||||
|
||||
&usb3 {
|
||||
status = "okay";
|
||||
qcom,no-wakeup-src-in-hostmode;
|
||||
};
|
||||
|
||||
&usb2s {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qusb_phy0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qusb_phy1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ssphy {
|
||||
status = "okay";
|
||||
};
|
|
@ -155,14 +155,27 @@
|
|||
<45 512 207108 14432000>;
|
||||
};
|
||||
|
||||
|
||||
subsys_notif_virt: qcom,subsys_notif_virt@2d000000 {
|
||||
compatible = "qcom,subsys-notif-virt";
|
||||
reg = <0x2d000000 0x18>;
|
||||
reg = <0x2d000000 0x400>;
|
||||
reg-names = "vdev_base";
|
||||
|
||||
adsp {
|
||||
subsys-name = "adsp";
|
||||
interrupts = <0 43 0>;
|
||||
interrupt-names = "state-irq";
|
||||
type = "virtual";
|
||||
offset = <0>;
|
||||
};
|
||||
wlan {
|
||||
subsys-name = "AR6320";
|
||||
offset = <16>;
|
||||
interrupts = <0 43 0>;
|
||||
interrupt-names = "state-irq";
|
||||
type = "virtual";
|
||||
offset = <512>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -12,10 +12,7 @@
|
|||
|
||||
/dts-v1/;
|
||||
|
||||
#include "skeleton64.dtsi"
|
||||
#include "vplatform-lfv-msm8996.dtsi"
|
||||
#include <dt-bindings/clock/msm-clocks-8996.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include "vplatform-lfv-msm8996-ivi-common.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Qualcomm Technologies, Inc. MSM 8996";
|
||||
|
@ -23,151 +20,14 @@
|
|||
qcom,msm-id = <246 0x0>;
|
||||
};
|
||||
|
||||
&soc {
|
||||
qcom,msm-audio-ion-vm {
|
||||
compatible = "qcom,msm-audio-ion-vm";
|
||||
qcom,smmu-enabled;
|
||||
};
|
||||
|
||||
qcom,hab {
|
||||
compatible = "qcom,hab";
|
||||
vmid = <2>;
|
||||
|
||||
mmidgrp100: mmidgrp100 {
|
||||
grp-start-id = <100>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp200: mmidgrp200 {
|
||||
grp-start-id = <200>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp300: mmidgrp300 {
|
||||
grp-start-id = <300>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp400: mmidgrp400 {
|
||||
grp-start-id = <400>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp500: mmidgrp500 {
|
||||
grp-start-id = <500>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp600: mmidgrp600 {
|
||||
grp-start-id = <600>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp700: mmidgrp700 {
|
||||
grp-start-id = <700>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp800: mmidgrp800 {
|
||||
grp-start-id = <800>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp900: mmidgrp900 {
|
||||
grp-start-id = <900>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
|
||||
mmidgrp1000: mmidgrp1000 {
|
||||
grp-start-id = <1000>;
|
||||
role = "fe";
|
||||
remote-vmids = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
qcom,cnss {
|
||||
compatible = "qcom,cnss";
|
||||
wlan-bootstrap-gpio = <&tlmm 46 0>;
|
||||
vdd-wlan-en-supply = <&wlan_en_vreg>;
|
||||
vdd-wlan-supply = <&rome_vreg>;
|
||||
vdd-wlan-io-supply = <&pm8994_s4>;
|
||||
vdd-wlan-xtal-supply = <&pm8994_l30>;
|
||||
vdd-wlan-core-supply = <&pm8994_s3>;
|
||||
wlan-ant-switch-supply = <&pm8994_l18_pin_ctrl>;
|
||||
qcom,wlan-en-vreg-support;
|
||||
qcom,notify-modem-status;
|
||||
pinctrl-names = "bootstrap_active", "bootstrap_sleep";
|
||||
pinctrl-0 = <&cnss_bootstrap_active>;
|
||||
pinctrl-1 = <&cnss_bootstrap_sleep>;
|
||||
|
||||
qcom,msm-bus,name = "msm-cnss";
|
||||
qcom,msm-bus,num-cases = <4>;
|
||||
qcom,msm-bus,num-paths = <1>;
|
||||
qcom,msm-bus,vectors-KBps =
|
||||
/* No vote */
|
||||
<45 512 0 0>,
|
||||
/* Up to 200 Mbps */
|
||||
<45 512 41421 1520000>,
|
||||
/* Up to 400 Mbps */
|
||||
<45 512 96650 1520000>,
|
||||
/* Up to 800 Mbps */
|
||||
<45 512 207108 14432000>;
|
||||
};
|
||||
|
||||
subsys_notif_virt: qcom,subsys_notif_virt@2D000000 {
|
||||
compatible = "qcom,subsys-notif-virt";
|
||||
reg = <0x2D000000 0x100>;
|
||||
reg-names = "vdev_base";
|
||||
adsp {
|
||||
subsys-name = "adsp";
|
||||
interrupts = <0 43 0>;
|
||||
interrupt-names = "state-irq";
|
||||
type = "virtual";
|
||||
offset = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&reserved_memory {
|
||||
pmem_shared: pmem_shared_region@d0000000 {
|
||||
reg = <0 0xd0000000 0 0x20000000>;
|
||||
pmem_shared: pmem_shared_region@1154ca000 {
|
||||
reg = <0x1 0x154ca000 0x0 0x154ca000>;
|
||||
label = "pmem_shared_mem";
|
||||
};
|
||||
|
||||
ion_system: ion_system_region@100000000 {
|
||||
reg = <0x1 0x0 0 0x10000000>;
|
||||
ion_system: ion_system_region@12a994000 {
|
||||
reg = <0x1 0x2a994000 0x0 0x154ca000>;
|
||||
label = "ion_system_mem";
|
||||
};
|
||||
};
|
||||
|
||||
#include "vplatform-lfv-msm8996-usb.dtsi"
|
||||
|
||||
&usb3 {
|
||||
status = "okay";
|
||||
qcom,no-wakeup-src-in-hostmode;
|
||||
};
|
||||
|
||||
&usb2s {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qusb_phy0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qusb_phy1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ssphy {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
33
arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi_8GB.dts
Normal file
33
arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi_8GB.dts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "vplatform-lfv-msm8996-ivi-common.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Qualcomm Technologies, Inc. MSM 8996";
|
||||
compatible = "qcom,msm8996";
|
||||
qcom,msm-id = <246 0x0>;
|
||||
};
|
||||
|
||||
&reserved_memory {
|
||||
pmem_shared: pmem_shared_region@13ff75000 {
|
||||
reg = <0x1 0x3ff75000 0x0 0x3ff75000>;
|
||||
label = "pmem_shared_mem";
|
||||
};
|
||||
|
||||
ion_system: ion_system_region@17feea000 {
|
||||
reg = <0x1 0x7feea000 0x0 0x3ff75000>;
|
||||
label = "ion_system_mem";
|
||||
};
|
||||
};
|
|
@ -145,9 +145,11 @@ CONFIG_USB_STORAGE=y
|
|||
CONFIG_USB_CHIPIDEA=y
|
||||
CONFIG_USB_CHIPIDEA_UDC=y
|
||||
CONFIG_USB_CHIPIDEA_HOST=y
|
||||
CONFIG_USB_CHIPIDEA_ULPI=y
|
||||
CONFIG_NOP_USB_XCEIV=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_ETH=m
|
||||
CONFIG_USB_ULPI_BUS=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
|
|
|
@ -261,6 +261,7 @@ CONFIG_USB_STORAGE=y
|
|||
CONFIG_USB_CHIPIDEA=y
|
||||
CONFIG_USB_CHIPIDEA_UDC=y
|
||||
CONFIG_USB_CHIPIDEA_HOST=y
|
||||
CONFIG_USB_CHIPIDEA_ULPI=y
|
||||
CONFIG_USB_SERIAL=m
|
||||
CONFIG_USB_SERIAL_GENERIC=y
|
||||
CONFIG_USB_SERIAL_FTDI_SIO=m
|
||||
|
@ -287,6 +288,7 @@ CONFIG_USB_G_NCM=m
|
|||
CONFIG_USB_GADGETFS=m
|
||||
CONFIG_USB_MASS_STORAGE=m
|
||||
CONFIG_USB_G_SERIAL=m
|
||||
CONFIG_USB_ULPI_BUS=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
|
|
|
@ -185,7 +185,7 @@ static int pxa_irq_suspend(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pxa_internal_irq_nr / 32; i++) {
|
||||
for (i = 0; i < DIV_ROUND_UP(pxa_internal_irq_nr, 32); i++) {
|
||||
void __iomem *base = irq_base(i);
|
||||
|
||||
saved_icmr[i] = __raw_readl(base + ICMR);
|
||||
|
@ -204,7 +204,7 @@ static void pxa_irq_resume(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pxa_internal_irq_nr / 32; i++) {
|
||||
for (i = 0; i < DIV_ROUND_UP(pxa_internal_irq_nr, 32); i++) {
|
||||
void __iomem *base = irq_base(i);
|
||||
|
||||
__raw_writel(saved_icmr[i], base + ICMR);
|
||||
|
|
|
@ -815,19 +815,28 @@ int __mark_rodata_ro(void *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kernel_set_to_readonly __read_mostly;
|
||||
|
||||
void mark_rodata_ro(void)
|
||||
{
|
||||
kernel_set_to_readonly = 1;
|
||||
stop_machine(__mark_rodata_ro, NULL, NULL);
|
||||
}
|
||||
|
||||
void set_kernel_text_rw(void)
|
||||
{
|
||||
if (!kernel_set_to_readonly)
|
||||
return;
|
||||
|
||||
set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), false,
|
||||
current->active_mm);
|
||||
}
|
||||
|
||||
void set_kernel_text_ro(void)
|
||||
{
|
||||
if (!kernel_set_to_readonly)
|
||||
return;
|
||||
|
||||
set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
|
||||
current->active_mm);
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ static void smp_store_cpu_info(unsigned int cpuid)
|
|||
* This is the secondary CPU boot entry. We're using this CPUs
|
||||
* idle thread stack, but a set of temporary page tables.
|
||||
*/
|
||||
asmlinkage void secondary_start_kernel(void)
|
||||
asmlinkage notrace void secondary_start_kernel(void)
|
||||
{
|
||||
struct mm_struct *mm = &init_mm;
|
||||
unsigned int cpu;
|
||||
|
|
|
@ -1373,12 +1373,12 @@ int pmd_clear_huge(pmd_t *pmd)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
|
||||
int pud_free_pmd_page(pud_t *pud)
|
||||
int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
{
|
||||
return pud_none(*pud);
|
||||
}
|
||||
|
||||
int pmd_free_pte_page(pmd_t *pmd)
|
||||
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
|
||||
{
|
||||
return pmd_none(*pmd);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
|
|||
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
|
||||
unsigned long address)
|
||||
{
|
||||
pgtable_page_dtor(page);
|
||||
__free_page(page);
|
||||
}
|
||||
|
||||
|
@ -73,8 +74,9 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
|
|||
return page;
|
||||
}
|
||||
|
||||
extern inline void pte_free(struct mm_struct *mm, struct page *page)
|
||||
static inline void pte_free(struct mm_struct *mm, struct page *page)
|
||||
{
|
||||
pgtable_page_dtor(page);
|
||||
__free_page(page);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x,
|
|||
{
|
||||
volatile unsigned int *a;
|
||||
|
||||
mb();
|
||||
a = __ldcw_align(x);
|
||||
while (__ldcw(a) == 0)
|
||||
while (*a == 0)
|
||||
|
@ -31,16 +30,15 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x,
|
|||
local_irq_disable();
|
||||
} else
|
||||
cpu_relax();
|
||||
mb();
|
||||
}
|
||||
|
||||
static inline void arch_spin_unlock(arch_spinlock_t *x)
|
||||
{
|
||||
volatile unsigned int *a;
|
||||
mb();
|
||||
|
||||
a = __ldcw_align(x);
|
||||
*a = 1;
|
||||
mb();
|
||||
*a = 1;
|
||||
}
|
||||
|
||||
static inline int arch_spin_trylock(arch_spinlock_t *x)
|
||||
|
@ -48,10 +46,8 @@ static inline int arch_spin_trylock(arch_spinlock_t *x)
|
|||
volatile unsigned int *a;
|
||||
int ret;
|
||||
|
||||
mb();
|
||||
a = __ldcw_align(x);
|
||||
ret = __ldcw(a) != 0;
|
||||
mb();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -627,12 +627,12 @@ cas_action:
|
|||
stw %r1, 4(%sr2,%r20)
|
||||
#endif
|
||||
/* The load and store could fail */
|
||||
1: ldw,ma 0(%r26), %r28
|
||||
1: ldw 0(%r26), %r28
|
||||
sub,<> %r28, %r25, %r0
|
||||
2: stw,ma %r24, 0(%r26)
|
||||
2: stw %r24, 0(%r26)
|
||||
/* Free lock */
|
||||
sync
|
||||
stw,ma %r20, 0(%sr2,%r20)
|
||||
stw %r20, 0(%sr2,%r20)
|
||||
#if ENABLE_LWS_DEBUG
|
||||
/* Clear thread register indicator */
|
||||
stw %r0, 4(%sr2,%r20)
|
||||
|
@ -796,30 +796,30 @@ cas2_action:
|
|||
ldo 1(%r0),%r28
|
||||
|
||||
/* 8bit CAS */
|
||||
13: ldb,ma 0(%r26), %r29
|
||||
13: ldb 0(%r26), %r29
|
||||
sub,= %r29, %r25, %r0
|
||||
b,n cas2_end
|
||||
14: stb,ma %r24, 0(%r26)
|
||||
14: stb %r24, 0(%r26)
|
||||
b cas2_end
|
||||
copy %r0, %r28
|
||||
nop
|
||||
nop
|
||||
|
||||
/* 16bit CAS */
|
||||
15: ldh,ma 0(%r26), %r29
|
||||
15: ldh 0(%r26), %r29
|
||||
sub,= %r29, %r25, %r0
|
||||
b,n cas2_end
|
||||
16: sth,ma %r24, 0(%r26)
|
||||
16: sth %r24, 0(%r26)
|
||||
b cas2_end
|
||||
copy %r0, %r28
|
||||
nop
|
||||
nop
|
||||
|
||||
/* 32bit CAS */
|
||||
17: ldw,ma 0(%r26), %r29
|
||||
17: ldw 0(%r26), %r29
|
||||
sub,= %r29, %r25, %r0
|
||||
b,n cas2_end
|
||||
18: stw,ma %r24, 0(%r26)
|
||||
18: stw %r24, 0(%r26)
|
||||
b cas2_end
|
||||
copy %r0, %r28
|
||||
nop
|
||||
|
@ -827,10 +827,10 @@ cas2_action:
|
|||
|
||||
/* 64bit CAS */
|
||||
#ifdef CONFIG_64BIT
|
||||
19: ldd,ma 0(%r26), %r29
|
||||
19: ldd 0(%r26), %r29
|
||||
sub,*= %r29, %r25, %r0
|
||||
b,n cas2_end
|
||||
20: std,ma %r24, 0(%r26)
|
||||
20: std %r24, 0(%r26)
|
||||
copy %r0, %r28
|
||||
#else
|
||||
/* Compare first word */
|
||||
|
@ -849,7 +849,7 @@ cas2_action:
|
|||
cas2_end:
|
||||
/* Free lock */
|
||||
sync
|
||||
stw,ma %r20, 0(%sr2,%r20)
|
||||
stw %r20, 0(%sr2,%r20)
|
||||
/* Enable interrupts */
|
||||
ssm PSW_SM_I, %r0
|
||||
/* Return to userspace, set no error */
|
||||
|
|
|
@ -48,6 +48,7 @@ CONFIG_X86_CPUID=y
|
|||
CONFIG_KSM=y
|
||||
CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_ZSMALLOC=y
|
||||
# CONFIG_MTRR is not set
|
||||
CONFIG_HZ_100=y
|
||||
CONFIG_KEXEC=y
|
||||
|
@ -199,6 +200,7 @@ CONFIG_DEBUG_DEVRES=y
|
|||
CONFIG_OF=y
|
||||
CONFIG_OF_UNITTEST=y
|
||||
# CONFIG_PNP_DEBUG_MESSAGES is not set
|
||||
CONFIG_ZRAM=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=8192
|
||||
|
@ -449,8 +451,9 @@ CONFIG_HARDENED_USERCOPY=y
|
|||
CONFIG_SECURITY_SELINUX=y
|
||||
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
|
||||
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
|
||||
CONFIG_CRYPTO_ECHAINIV=y
|
||||
CONFIG_CRYPTO_SHA512=y
|
||||
CONFIG_CRYPTO_LZ4=y
|
||||
CONFIG_CRYPTO_ZSTD=y
|
||||
CONFIG_ASYMMETRIC_KEY_TYPE=y
|
||||
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
|
||||
CONFIG_X509_CERTIFICATE_PARSER=y
|
||||
|
|
|
@ -109,8 +109,7 @@ static inline int init_new_context(struct task_struct *tsk,
|
|||
struct mm_struct *mm)
|
||||
{
|
||||
mm->context.ctx_id = atomic64_inc_return(&last_mm_ctx_id);
|
||||
init_new_context_ldt(tsk, mm);
|
||||
return 0;
|
||||
return init_new_context_ldt(tsk, mm);
|
||||
}
|
||||
static inline void destroy_context(struct mm_struct *mm)
|
||||
{
|
||||
|
|
|
@ -4,9 +4,18 @@
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* A clear pte value is special, and doesn't get inverted.
|
||||
*
|
||||
* Note that even users that only pass a pgprot_t (rather
|
||||
* than a full pte) won't trigger the special zero case,
|
||||
* because even PAGE_NONE has _PAGE_PROTNONE | _PAGE_ACCESSED
|
||||
* set. So the all zero case really is limited to just the
|
||||
* cleared page table entry case.
|
||||
*/
|
||||
static inline bool __pte_needs_invert(u64 val)
|
||||
{
|
||||
return !(val & _PAGE_PRESENT);
|
||||
return val && !(val & _PAGE_PRESENT);
|
||||
}
|
||||
|
||||
/* Get a mask to xor with the page table entry to get the correct pfn. */
|
||||
|
|
|
@ -173,6 +173,11 @@ static inline unsigned long pud_pfn(pud_t pud)
|
|||
return (pfn & pud_pfn_mask(pud)) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static inline unsigned long pgd_pfn(pgd_t pgd)
|
||||
{
|
||||
return (pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
#define pte_page(pte) pfn_to_page(pte_pfn(pte))
|
||||
|
||||
static inline int pmd_large(pmd_t pte)
|
||||
|
@ -578,8 +583,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
|
|||
* Currently stuck as a macro due to indirect forward reference to
|
||||
* linux/mmzone.h's __section_mem_map_addr() definition:
|
||||
*/
|
||||
#define pmd_page(pmd) \
|
||||
pfn_to_page((pmd_val(pmd) & pmd_pfn_mask(pmd)) >> PAGE_SHIFT)
|
||||
#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd))
|
||||
|
||||
/*
|
||||
* the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
|
||||
|
@ -647,8 +651,7 @@ static inline unsigned long pud_page_vaddr(pud_t pud)
|
|||
* Currently stuck as a macro due to indirect forward reference to
|
||||
* linux/mmzone.h's __section_mem_map_addr() definition:
|
||||
*/
|
||||
#define pud_page(pud) \
|
||||
pfn_to_page((pud_val(pud) & pud_pfn_mask(pud)) >> PAGE_SHIFT)
|
||||
#define pud_page(pud) pfn_to_page(pud_pfn(pud))
|
||||
|
||||
/* Find an entry in the second-level page table.. */
|
||||
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
|
||||
|
@ -688,7 +691,7 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd)
|
|||
* Currently stuck as a macro due to indirect forward reference to
|
||||
* linux/mmzone.h's __section_mem_map_addr() definition:
|
||||
*/
|
||||
#define pgd_page(pgd) pfn_to_page(pgd_val(pgd) >> PAGE_SHIFT)
|
||||
#define pgd_page(pgd) pfn_to_page(pgd_pfn(pgd))
|
||||
|
||||
/* to find an entry in a page-table-directory. */
|
||||
static inline unsigned long pud_index(unsigned long address)
|
||||
|
|
|
@ -1006,7 +1006,7 @@ static int populate_pmd(struct cpa_data *cpa,
|
|||
|
||||
pmd = pmd_offset(pud, start);
|
||||
|
||||
set_pmd(pmd, pmd_mkhuge(pfn_pmd(cpa->pfn,
|
||||
set_pmd(pmd, pmd_mkhuge(pfn_pmd(cpa->pfn >> PAGE_SHIFT,
|
||||
canon_pgprot(pmd_pgprot))));
|
||||
|
||||
start += PMD_SIZE;
|
||||
|
|
|
@ -676,28 +676,50 @@ int pmd_clear_huge(pmd_t *pmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/**
|
||||
* pud_free_pmd_page - Clear pud entry and free pmd page.
|
||||
* @pud: Pointer to a PUD.
|
||||
* @addr: Virtual address associated with pud.
|
||||
*
|
||||
* Context: The pud range has been unmaped and TLB purged.
|
||||
* Context: The pud range has been unmapped and TLB purged.
|
||||
* Return: 1 if clearing the entry succeeded. 0 otherwise.
|
||||
*
|
||||
* NOTE: Callers must allow a single page allocation.
|
||||
*/
|
||||
int pud_free_pmd_page(pud_t *pud)
|
||||
int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
pmd_t *pmd, *pmd_sv;
|
||||
pte_t *pte;
|
||||
int i;
|
||||
|
||||
if (pud_none(*pud))
|
||||
return 1;
|
||||
|
||||
pmd = (pmd_t *)pud_page_vaddr(*pud);
|
||||
pmd_sv = (pmd_t *)__get_free_page(GFP_KERNEL);
|
||||
if (!pmd_sv)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; i++)
|
||||
if (!pmd_free_pte_page(&pmd[i]))
|
||||
return 0;
|
||||
for (i = 0; i < PTRS_PER_PMD; i++) {
|
||||
pmd_sv[i] = pmd[i];
|
||||
if (!pmd_none(pmd[i]))
|
||||
pmd_clear(&pmd[i]);
|
||||
}
|
||||
|
||||
pud_clear(pud);
|
||||
|
||||
/* INVLPG to clear all paging-structure caches */
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; i++) {
|
||||
if (!pmd_none(pmd_sv[i])) {
|
||||
pte = (pte_t *)pmd_page_vaddr(pmd_sv[i]);
|
||||
free_page((unsigned long)pte);
|
||||
}
|
||||
}
|
||||
|
||||
free_page((unsigned long)pmd_sv);
|
||||
free_page((unsigned long)pmd);
|
||||
|
||||
return 1;
|
||||
|
@ -706,11 +728,12 @@ int pud_free_pmd_page(pud_t *pud)
|
|||
/**
|
||||
* pmd_free_pte_page - Clear pmd entry and free pte page.
|
||||
* @pmd: Pointer to a PMD.
|
||||
* @addr: Virtual address associated with pmd.
|
||||
*
|
||||
* Context: The pmd range has been unmaped and TLB purged.
|
||||
* Context: The pmd range has been unmapped and TLB purged.
|
||||
* Return: 1 if clearing the entry succeeded. 0 otherwise.
|
||||
*/
|
||||
int pmd_free_pte_page(pmd_t *pmd)
|
||||
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
|
||||
{
|
||||
pte_t *pte;
|
||||
|
||||
|
@ -719,8 +742,30 @@ int pmd_free_pte_page(pmd_t *pmd)
|
|||
|
||||
pte = (pte_t *)pmd_page_vaddr(*pmd);
|
||||
pmd_clear(pmd);
|
||||
|
||||
/* INVLPG to clear all paging-structure caches */
|
||||
flush_tlb_kernel_range(addr, addr + PAGE_SIZE-1);
|
||||
|
||||
free_page((unsigned long)pte);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_X86_64 */
|
||||
|
||||
int pud_free_pmd_page(pud_t *pud, unsigned long addr)
|
||||
{
|
||||
return pud_none(*pud);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable free page handling on x86-PAE. This assures that ioremap()
|
||||
* does not update sync'd pmd entries. See vmalloc_sync_one().
|
||||
*/
|
||||
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
|
||||
{
|
||||
return pmd_none(*pmd);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_X86_64 */
|
||||
#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
|
||||
|
|
|
@ -1577,6 +1577,15 @@ config CRYPTO_LZ4HC
|
|||
help
|
||||
This is the LZ4 high compression mode algorithm.
|
||||
|
||||
config CRYPTO_ZSTD
|
||||
tristate "Zstd compression algorithm"
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_ACOMP2
|
||||
select ZSTD_COMPRESS
|
||||
select ZSTD_DECOMPRESS
|
||||
help
|
||||
This is the zstd algorithm.
|
||||
|
||||
comment "Random Number Generation"
|
||||
|
||||
config CRYPTO_ANSI_CPRNG
|
||||
|
|
|
@ -126,6 +126,7 @@ obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
|
|||
obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
|
||||
obj-$(CONFIG_CRYPTO_USER_API_RNG) += algif_rng.o
|
||||
obj-$(CONFIG_CRYPTO_USER_API_AEAD) += algif_aead.o
|
||||
obj-$(CONFIG_CRYPTO_ZSTD) += zstd.o
|
||||
|
||||
#
|
||||
# generic algorithms and the async_tx api
|
||||
|
|
|
@ -73,11 +73,9 @@ static inline u8 *ablkcipher_get_spot(u8 *start, unsigned int len)
|
|||
return max(start, end_page);
|
||||
}
|
||||
|
||||
static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk,
|
||||
unsigned int bsize)
|
||||
static inline void ablkcipher_done_slow(struct ablkcipher_walk *walk,
|
||||
unsigned int n)
|
||||
{
|
||||
unsigned int n = bsize;
|
||||
|
||||
for (;;) {
|
||||
unsigned int len_this_page = scatterwalk_pagelen(&walk->out);
|
||||
|
||||
|
@ -89,17 +87,13 @@ static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk,
|
|||
n -= len_this_page;
|
||||
scatterwalk_start(&walk->out, sg_next(walk->out.sg));
|
||||
}
|
||||
|
||||
return bsize;
|
||||
}
|
||||
|
||||
static inline unsigned int ablkcipher_done_fast(struct ablkcipher_walk *walk,
|
||||
unsigned int n)
|
||||
static inline void ablkcipher_done_fast(struct ablkcipher_walk *walk,
|
||||
unsigned int n)
|
||||
{
|
||||
scatterwalk_advance(&walk->in, n);
|
||||
scatterwalk_advance(&walk->out, n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int ablkcipher_walk_next(struct ablkcipher_request *req,
|
||||
|
@ -109,39 +103,40 @@ int ablkcipher_walk_done(struct ablkcipher_request *req,
|
|||
struct ablkcipher_walk *walk, int err)
|
||||
{
|
||||
struct crypto_tfm *tfm = req->base.tfm;
|
||||
unsigned int nbytes = 0;
|
||||
unsigned int n; /* bytes processed */
|
||||
bool more;
|
||||
|
||||
if (likely(err >= 0)) {
|
||||
unsigned int n = walk->nbytes - err;
|
||||
if (unlikely(err < 0))
|
||||
goto finish;
|
||||
|
||||
if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW)))
|
||||
n = ablkcipher_done_fast(walk, n);
|
||||
else if (WARN_ON(err)) {
|
||||
n = walk->nbytes - err;
|
||||
walk->total -= n;
|
||||
more = (walk->total != 0);
|
||||
|
||||
if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW))) {
|
||||
ablkcipher_done_fast(walk, n);
|
||||
} else {
|
||||
if (WARN_ON(err)) {
|
||||
/* unexpected case; didn't process all bytes */
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
} else
|
||||
n = ablkcipher_done_slow(walk, n);
|
||||
|
||||
nbytes = walk->total - n;
|
||||
err = 0;
|
||||
goto finish;
|
||||
}
|
||||
ablkcipher_done_slow(walk, n);
|
||||
}
|
||||
|
||||
scatterwalk_done(&walk->in, 0, nbytes);
|
||||
scatterwalk_done(&walk->out, 1, nbytes);
|
||||
scatterwalk_done(&walk->in, 0, more);
|
||||
scatterwalk_done(&walk->out, 1, more);
|
||||
|
||||
err:
|
||||
walk->total = nbytes;
|
||||
walk->nbytes = nbytes;
|
||||
|
||||
if (nbytes) {
|
||||
if (more) {
|
||||
crypto_yield(req->base.flags);
|
||||
return ablkcipher_walk_next(req, walk);
|
||||
}
|
||||
|
||||
err = 0;
|
||||
finish:
|
||||
walk->nbytes = 0;
|
||||
if (walk->iv != req->info)
|
||||
memcpy(req->info, walk->iv, tfm->crt_ablkcipher.ivsize);
|
||||
kfree(walk->iv_buffer);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ablkcipher_walk_done);
|
||||
|
|
|
@ -71,19 +71,18 @@ static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len)
|
|||
return max(start, end_page);
|
||||
}
|
||||
|
||||
static inline unsigned int blkcipher_done_slow(struct blkcipher_walk *walk,
|
||||
unsigned int bsize)
|
||||
static inline void blkcipher_done_slow(struct blkcipher_walk *walk,
|
||||
unsigned int bsize)
|
||||
{
|
||||
u8 *addr;
|
||||
|
||||
addr = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1);
|
||||
addr = blkcipher_get_spot(addr, bsize);
|
||||
scatterwalk_copychunks(addr, &walk->out, bsize, 1);
|
||||
return bsize;
|
||||
}
|
||||
|
||||
static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk,
|
||||
unsigned int n)
|
||||
static inline void blkcipher_done_fast(struct blkcipher_walk *walk,
|
||||
unsigned int n)
|
||||
{
|
||||
if (walk->flags & BLKCIPHER_WALK_COPY) {
|
||||
blkcipher_map_dst(walk);
|
||||
|
@ -97,49 +96,48 @@ static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk,
|
|||
|
||||
scatterwalk_advance(&walk->in, n);
|
||||
scatterwalk_advance(&walk->out, n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int blkcipher_walk_done(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk, int err)
|
||||
{
|
||||
unsigned int nbytes = 0;
|
||||
unsigned int n; /* bytes processed */
|
||||
bool more;
|
||||
|
||||
if (likely(err >= 0)) {
|
||||
unsigned int n = walk->nbytes - err;
|
||||
if (unlikely(err < 0))
|
||||
goto finish;
|
||||
|
||||
if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW)))
|
||||
n = blkcipher_done_fast(walk, n);
|
||||
else if (WARN_ON(err)) {
|
||||
n = walk->nbytes - err;
|
||||
walk->total -= n;
|
||||
more = (walk->total != 0);
|
||||
|
||||
if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) {
|
||||
blkcipher_done_fast(walk, n);
|
||||
} else {
|
||||
if (WARN_ON(err)) {
|
||||
/* unexpected case; didn't process all bytes */
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
} else
|
||||
n = blkcipher_done_slow(walk, n);
|
||||
|
||||
nbytes = walk->total - n;
|
||||
err = 0;
|
||||
goto finish;
|
||||
}
|
||||
blkcipher_done_slow(walk, n);
|
||||
}
|
||||
|
||||
scatterwalk_done(&walk->in, 0, nbytes);
|
||||
scatterwalk_done(&walk->out, 1, nbytes);
|
||||
scatterwalk_done(&walk->in, 0, more);
|
||||
scatterwalk_done(&walk->out, 1, more);
|
||||
|
||||
err:
|
||||
walk->total = nbytes;
|
||||
walk->nbytes = nbytes;
|
||||
|
||||
if (nbytes) {
|
||||
if (more) {
|
||||
crypto_yield(desc->flags);
|
||||
return blkcipher_walk_next(desc, walk);
|
||||
}
|
||||
|
||||
err = 0;
|
||||
finish:
|
||||
walk->nbytes = 0;
|
||||
if (walk->iv != desc->info)
|
||||
memcpy(desc->info, walk->iv, walk->ivsize);
|
||||
if (walk->buffer != walk->page)
|
||||
kfree(walk->buffer);
|
||||
if (walk->page)
|
||||
free_page((unsigned long)walk->page);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blkcipher_walk_done);
|
||||
|
|
|
@ -3949,6 +3949,22 @@ static const struct alg_test_desc alg_test_descs[] = {
|
|||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
.alg = "zstd",
|
||||
.test = alg_test_comp,
|
||||
.fips_allowed = 1,
|
||||
.suite = {
|
||||
.comp = {
|
||||
.comp = {
|
||||
.vecs = zstd_comp_tv_template,
|
||||
.count = ZSTD_COMP_TEST_VECTORS
|
||||
},
|
||||
.decomp = {
|
||||
.vecs = zstd_decomp_tv_template,
|
||||
.count = ZSTD_DECOMP_TEST_VECTORS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -35331,4 +35331,78 @@ static struct comp_testvec lz4hc_decomp_tv_template[] = {
|
|||
},
|
||||
};
|
||||
|
||||
#define ZSTD_COMP_TEST_VECTORS 2
|
||||
#define ZSTD_DECOMP_TEST_VECTORS 2
|
||||
|
||||
static struct comp_testvec zstd_comp_tv_template[] = {
|
||||
{
|
||||
.inlen = 68,
|
||||
.outlen = 39,
|
||||
.input = "The algorithm is zstd. "
|
||||
"The algorithm is zstd. "
|
||||
"The algorithm is zstd.",
|
||||
.output = "\x28\xb5\x2f\xfd\x00\x50\xf5\x00\x00\xb8\x54\x68\x65"
|
||||
"\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x20\x69\x73"
|
||||
"\x20\x7a\x73\x74\x64\x2e\x20\x01\x00\x55\x73\x36\x01"
|
||||
,
|
||||
},
|
||||
{
|
||||
.inlen = 244,
|
||||
.outlen = 151,
|
||||
.input = "zstd, short for Zstandard, is a fast lossless "
|
||||
"compression algorithm, targeting real-time "
|
||||
"compression scenarios at zlib-level and better "
|
||||
"compression ratios. The zstd compression library "
|
||||
"provides in-memory compression and decompression "
|
||||
"functions.",
|
||||
.output = "\x28\xb5\x2f\xfd\x00\x50\x75\x04\x00\x42\x4b\x1e\x17"
|
||||
"\x90\x81\x31\x00\xf2\x2f\xe4\x36\xc9\xef\x92\x88\x32"
|
||||
"\xc9\xf2\x24\x94\xd8\x68\x9a\x0f\x00\x0c\xc4\x31\x6f"
|
||||
"\x0d\x0c\x38\xac\x5c\x48\x03\xcd\x63\x67\xc0\xf3\xad"
|
||||
"\x4e\x90\xaa\x78\xa0\xa4\xc5\x99\xda\x2f\xb6\x24\x60"
|
||||
"\xe2\x79\x4b\xaa\xb6\x6b\x85\x0b\xc9\xc6\x04\x66\x86"
|
||||
"\xe2\xcc\xe2\x25\x3f\x4f\x09\xcd\xb8\x9d\xdb\xc1\x90"
|
||||
"\xa9\x11\xbc\x35\x44\x69\x2d\x9c\x64\x4f\x13\x31\x64"
|
||||
"\xcc\xfb\x4d\x95\x93\x86\x7f\x33\x7f\x1a\xef\xe9\x30"
|
||||
"\xf9\x67\xa1\x94\x0a\x69\x0f\x60\xcd\xc3\xab\x99\xdc"
|
||||
"\x42\xed\x97\x05\x00\x33\xc3\x15\x95\x3a\x06\xa0\x0e"
|
||||
"\x20\xa9\x0e\x82\xb9\x43\x45\x01",
|
||||
},
|
||||
};
|
||||
|
||||
static struct comp_testvec zstd_decomp_tv_template[] = {
|
||||
{
|
||||
.inlen = 43,
|
||||
.outlen = 68,
|
||||
.input = "\x28\xb5\x2f\xfd\x04\x50\xf5\x00\x00\xb8\x54\x68\x65"
|
||||
"\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x20\x69\x73"
|
||||
"\x20\x7a\x73\x74\x64\x2e\x20\x01\x00\x55\x73\x36\x01"
|
||||
"\x6b\xf4\x13\x35",
|
||||
.output = "The algorithm is zstd. "
|
||||
"The algorithm is zstd. "
|
||||
"The algorithm is zstd.",
|
||||
},
|
||||
{
|
||||
.inlen = 155,
|
||||
.outlen = 244,
|
||||
.input = "\x28\xb5\x2f\xfd\x04\x50\x75\x04\x00\x42\x4b\x1e\x17"
|
||||
"\x90\x81\x31\x00\xf2\x2f\xe4\x36\xc9\xef\x92\x88\x32"
|
||||
"\xc9\xf2\x24\x94\xd8\x68\x9a\x0f\x00\x0c\xc4\x31\x6f"
|
||||
"\x0d\x0c\x38\xac\x5c\x48\x03\xcd\x63\x67\xc0\xf3\xad"
|
||||
"\x4e\x90\xaa\x78\xa0\xa4\xc5\x99\xda\x2f\xb6\x24\x60"
|
||||
"\xe2\x79\x4b\xaa\xb6\x6b\x85\x0b\xc9\xc6\x04\x66\x86"
|
||||
"\xe2\xcc\xe2\x25\x3f\x4f\x09\xcd\xb8\x9d\xdb\xc1\x90"
|
||||
"\xa9\x11\xbc\x35\x44\x69\x2d\x9c\x64\x4f\x13\x31\x64"
|
||||
"\xcc\xfb\x4d\x95\x93\x86\x7f\x33\x7f\x1a\xef\xe9\x30"
|
||||
"\xf9\x67\xa1\x94\x0a\x69\x0f\x60\xcd\xc3\xab\x99\xdc"
|
||||
"\x42\xed\x97\x05\x00\x33\xc3\x15\x95\x3a\x06\xa0\x0e"
|
||||
"\x20\xa9\x0e\x82\xb9\x43\x45\x01\xaa\x6d\xda\x0d",
|
||||
.output = "zstd, short for Zstandard, is a fast lossless "
|
||||
"compression algorithm, targeting real-time "
|
||||
"compression scenarios at zlib-level and better "
|
||||
"compression ratios. The zstd compression library "
|
||||
"provides in-memory compression and decompression "
|
||||
"functions.",
|
||||
},
|
||||
};
|
||||
#endif /* _CRYPTO_TESTMGR_H */
|
||||
|
|
432
crypto/vmac.c
432
crypto/vmac.c
|
@ -1,6 +1,10 @@
|
|||
/*
|
||||
* Modified to interface to the Linux kernel
|
||||
* VMAC: Message Authentication Code using Universal Hashing
|
||||
*
|
||||
* Reference: https://tools.ietf.org/html/draft-krovetz-vmac-01
|
||||
*
|
||||
* Copyright (c) 2009, Intel Corporation.
|
||||
* Copyright (c) 2018, Google Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
|
@ -16,14 +20,15 @@
|
|||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai.
|
||||
* This implementation is herby placed in the public domain.
|
||||
* The authors offers no warranty. Use at your own risk.
|
||||
* Please send bug reports to the authors.
|
||||
* Last modified: 17 APR 08, 1700 PDT
|
||||
* ----------------------------------------------------------------------- */
|
||||
/*
|
||||
* Derived from:
|
||||
* VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai.
|
||||
* This implementation is herby placed in the public domain.
|
||||
* The authors offers no warranty. Use at your own risk.
|
||||
* Last modified: 17 APR 08, 1700 PDT
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
|
@ -31,9 +36,35 @@
|
|||
#include <linux/scatterlist.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/vmac.h>
|
||||
#include <crypto/internal/hash.h>
|
||||
|
||||
/*
|
||||
* User definable settings.
|
||||
*/
|
||||
#define VMAC_TAG_LEN 64
|
||||
#define VMAC_KEY_SIZE 128/* Must be 128, 192 or 256 */
|
||||
#define VMAC_KEY_LEN (VMAC_KEY_SIZE/8)
|
||||
#define VMAC_NHBYTES 128/* Must 2^i for any 3 < i < 13 Standard = 128*/
|
||||
|
||||
/* per-transform (per-key) context */
|
||||
struct vmac_tfm_ctx {
|
||||
struct crypto_cipher *cipher;
|
||||
u64 nhkey[(VMAC_NHBYTES/8)+2*(VMAC_TAG_LEN/64-1)];
|
||||
u64 polykey[2*VMAC_TAG_LEN/64];
|
||||
u64 l3key[2*VMAC_TAG_LEN/64];
|
||||
};
|
||||
|
||||
/* per-request context */
|
||||
struct vmac_desc_ctx {
|
||||
union {
|
||||
u8 partial[VMAC_NHBYTES]; /* partial block */
|
||||
__le64 partial_words[VMAC_NHBYTES / 8];
|
||||
};
|
||||
unsigned int partial_size; /* size of the partial block */
|
||||
bool first_block_processed;
|
||||
u64 polytmp[2*VMAC_TAG_LEN/64]; /* running total of L2-hash */
|
||||
};
|
||||
|
||||
/*
|
||||
* Constants and masks
|
||||
*/
|
||||
|
@ -318,13 +349,6 @@ static void poly_step_func(u64 *ahi, u64 *alo,
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
static void vhash_abort(struct vmac_ctx *ctx)
|
||||
{
|
||||
ctx->polytmp[0] = ctx->polykey[0] ;
|
||||
ctx->polytmp[1] = ctx->polykey[1] ;
|
||||
ctx->first_block_processed = 0;
|
||||
}
|
||||
|
||||
static u64 l3hash(u64 p1, u64 p2, u64 k1, u64 k2, u64 len)
|
||||
{
|
||||
u64 rh, rl, t, z = 0;
|
||||
|
@ -364,280 +388,209 @@ static u64 l3hash(u64 p1, u64 p2, u64 k1, u64 k2, u64 len)
|
|||
return rl;
|
||||
}
|
||||
|
||||
static void vhash_update(const unsigned char *m,
|
||||
unsigned int mbytes, /* Pos multiple of VMAC_NHBYTES */
|
||||
struct vmac_ctx *ctx)
|
||||
/* L1 and L2-hash one or more VMAC_NHBYTES-byte blocks */
|
||||
static void vhash_blocks(const struct vmac_tfm_ctx *tctx,
|
||||
struct vmac_desc_ctx *dctx,
|
||||
const __le64 *mptr, unsigned int blocks)
|
||||
{
|
||||
u64 rh, rl, *mptr;
|
||||
const u64 *kptr = (u64 *)ctx->nhkey;
|
||||
int i;
|
||||
u64 ch, cl;
|
||||
u64 pkh = ctx->polykey[0];
|
||||
u64 pkl = ctx->polykey[1];
|
||||
const u64 *kptr = tctx->nhkey;
|
||||
const u64 pkh = tctx->polykey[0];
|
||||
const u64 pkl = tctx->polykey[1];
|
||||
u64 ch = dctx->polytmp[0];
|
||||
u64 cl = dctx->polytmp[1];
|
||||
u64 rh, rl;
|
||||
|
||||
if (!mbytes)
|
||||
return;
|
||||
|
||||
BUG_ON(mbytes % VMAC_NHBYTES);
|
||||
|
||||
mptr = (u64 *)m;
|
||||
i = mbytes / VMAC_NHBYTES; /* Must be non-zero */
|
||||
|
||||
ch = ctx->polytmp[0];
|
||||
cl = ctx->polytmp[1];
|
||||
|
||||
if (!ctx->first_block_processed) {
|
||||
ctx->first_block_processed = 1;
|
||||
if (!dctx->first_block_processed) {
|
||||
dctx->first_block_processed = true;
|
||||
nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, rh, rl);
|
||||
rh &= m62;
|
||||
ADD128(ch, cl, rh, rl);
|
||||
mptr += (VMAC_NHBYTES/sizeof(u64));
|
||||
i--;
|
||||
blocks--;
|
||||
}
|
||||
|
||||
while (i--) {
|
||||
while (blocks--) {
|
||||
nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, rh, rl);
|
||||
rh &= m62;
|
||||
poly_step(ch, cl, pkh, pkl, rh, rl);
|
||||
mptr += (VMAC_NHBYTES/sizeof(u64));
|
||||
}
|
||||
|
||||
ctx->polytmp[0] = ch;
|
||||
ctx->polytmp[1] = cl;
|
||||
dctx->polytmp[0] = ch;
|
||||
dctx->polytmp[1] = cl;
|
||||
}
|
||||
|
||||
static u64 vhash(unsigned char m[], unsigned int mbytes,
|
||||
u64 *tagl, struct vmac_ctx *ctx)
|
||||
static int vmac_setkey(struct crypto_shash *tfm,
|
||||
const u8 *key, unsigned int keylen)
|
||||
{
|
||||
u64 rh, rl, *mptr;
|
||||
const u64 *kptr = (u64 *)ctx->nhkey;
|
||||
int i, remaining;
|
||||
u64 ch, cl;
|
||||
u64 pkh = ctx->polykey[0];
|
||||
u64 pkl = ctx->polykey[1];
|
||||
struct vmac_tfm_ctx *tctx = crypto_shash_ctx(tfm);
|
||||
__be64 out[2];
|
||||
u8 in[16] = { 0 };
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
mptr = (u64 *)m;
|
||||
i = mbytes / VMAC_NHBYTES;
|
||||
remaining = mbytes % VMAC_NHBYTES;
|
||||
|
||||
if (ctx->first_block_processed) {
|
||||
ch = ctx->polytmp[0];
|
||||
cl = ctx->polytmp[1];
|
||||
} else if (i) {
|
||||
nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, ch, cl);
|
||||
ch &= m62;
|
||||
ADD128(ch, cl, pkh, pkl);
|
||||
mptr += (VMAC_NHBYTES/sizeof(u64));
|
||||
i--;
|
||||
} else if (remaining) {
|
||||
nh_16(mptr, kptr, 2*((remaining+15)/16), ch, cl);
|
||||
ch &= m62;
|
||||
ADD128(ch, cl, pkh, pkl);
|
||||
mptr += (VMAC_NHBYTES/sizeof(u64));
|
||||
goto do_l3;
|
||||
} else {/* Empty String */
|
||||
ch = pkh; cl = pkl;
|
||||
goto do_l3;
|
||||
if (keylen != VMAC_KEY_LEN) {
|
||||
crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (i--) {
|
||||
nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, rh, rl);
|
||||
rh &= m62;
|
||||
poly_step(ch, cl, pkh, pkl, rh, rl);
|
||||
mptr += (VMAC_NHBYTES/sizeof(u64));
|
||||
}
|
||||
if (remaining) {
|
||||
nh_16(mptr, kptr, 2*((remaining+15)/16), rh, rl);
|
||||
rh &= m62;
|
||||
poly_step(ch, cl, pkh, pkl, rh, rl);
|
||||
}
|
||||
|
||||
do_l3:
|
||||
vhash_abort(ctx);
|
||||
remaining *= 8;
|
||||
return l3hash(ch, cl, ctx->l3key[0], ctx->l3key[1], remaining);
|
||||
}
|
||||
|
||||
static u64 vmac(unsigned char m[], unsigned int mbytes,
|
||||
const unsigned char n[16], u64 *tagl,
|
||||
struct vmac_ctx_t *ctx)
|
||||
{
|
||||
u64 *in_n, *out_p;
|
||||
u64 p, h;
|
||||
int i;
|
||||
|
||||
in_n = ctx->__vmac_ctx.cached_nonce;
|
||||
out_p = ctx->__vmac_ctx.cached_aes;
|
||||
|
||||
i = n[15] & 1;
|
||||
if ((*(u64 *)(n+8) != in_n[1]) || (*(u64 *)(n) != in_n[0])) {
|
||||
in_n[0] = *(u64 *)(n);
|
||||
in_n[1] = *(u64 *)(n+8);
|
||||
((unsigned char *)in_n)[15] &= 0xFE;
|
||||
crypto_cipher_encrypt_one(ctx->child,
|
||||
(unsigned char *)out_p, (unsigned char *)in_n);
|
||||
|
||||
((unsigned char *)in_n)[15] |= (unsigned char)(1-i);
|
||||
}
|
||||
p = be64_to_cpup(out_p + i);
|
||||
h = vhash(m, mbytes, (u64 *)0, &ctx->__vmac_ctx);
|
||||
return le64_to_cpu(p + h);
|
||||
}
|
||||
|
||||
static int vmac_set_key(unsigned char user_key[], struct vmac_ctx_t *ctx)
|
||||
{
|
||||
u64 in[2] = {0}, out[2];
|
||||
unsigned i;
|
||||
int err = 0;
|
||||
|
||||
err = crypto_cipher_setkey(ctx->child, user_key, VMAC_KEY_LEN);
|
||||
err = crypto_cipher_setkey(tctx->cipher, key, keylen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Fill nh key */
|
||||
((unsigned char *)in)[0] = 0x80;
|
||||
for (i = 0; i < sizeof(ctx->__vmac_ctx.nhkey)/8; i += 2) {
|
||||
crypto_cipher_encrypt_one(ctx->child,
|
||||
(unsigned char *)out, (unsigned char *)in);
|
||||
ctx->__vmac_ctx.nhkey[i] = be64_to_cpup(out);
|
||||
ctx->__vmac_ctx.nhkey[i+1] = be64_to_cpup(out+1);
|
||||
((unsigned char *)in)[15] += 1;
|
||||
in[0] = 0x80;
|
||||
for (i = 0; i < ARRAY_SIZE(tctx->nhkey); i += 2) {
|
||||
crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in);
|
||||
tctx->nhkey[i] = be64_to_cpu(out[0]);
|
||||
tctx->nhkey[i+1] = be64_to_cpu(out[1]);
|
||||
in[15]++;
|
||||
}
|
||||
|
||||
/* Fill poly key */
|
||||
((unsigned char *)in)[0] = 0xC0;
|
||||
in[1] = 0;
|
||||
for (i = 0; i < sizeof(ctx->__vmac_ctx.polykey)/8; i += 2) {
|
||||
crypto_cipher_encrypt_one(ctx->child,
|
||||
(unsigned char *)out, (unsigned char *)in);
|
||||
ctx->__vmac_ctx.polytmp[i] =
|
||||
ctx->__vmac_ctx.polykey[i] =
|
||||
be64_to_cpup(out) & mpoly;
|
||||
ctx->__vmac_ctx.polytmp[i+1] =
|
||||
ctx->__vmac_ctx.polykey[i+1] =
|
||||
be64_to_cpup(out+1) & mpoly;
|
||||
((unsigned char *)in)[15] += 1;
|
||||
in[0] = 0xC0;
|
||||
in[15] = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(tctx->polykey); i += 2) {
|
||||
crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in);
|
||||
tctx->polykey[i] = be64_to_cpu(out[0]) & mpoly;
|
||||
tctx->polykey[i+1] = be64_to_cpu(out[1]) & mpoly;
|
||||
in[15]++;
|
||||
}
|
||||
|
||||
/* Fill ip key */
|
||||
((unsigned char *)in)[0] = 0xE0;
|
||||
in[1] = 0;
|
||||
for (i = 0; i < sizeof(ctx->__vmac_ctx.l3key)/8; i += 2) {
|
||||
in[0] = 0xE0;
|
||||
in[15] = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(tctx->l3key); i += 2) {
|
||||
do {
|
||||
crypto_cipher_encrypt_one(ctx->child,
|
||||
(unsigned char *)out, (unsigned char *)in);
|
||||
ctx->__vmac_ctx.l3key[i] = be64_to_cpup(out);
|
||||
ctx->__vmac_ctx.l3key[i+1] = be64_to_cpup(out+1);
|
||||
((unsigned char *)in)[15] += 1;
|
||||
} while (ctx->__vmac_ctx.l3key[i] >= p64
|
||||
|| ctx->__vmac_ctx.l3key[i+1] >= p64);
|
||||
crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in);
|
||||
tctx->l3key[i] = be64_to_cpu(out[0]);
|
||||
tctx->l3key[i+1] = be64_to_cpu(out[1]);
|
||||
in[15]++;
|
||||
} while (tctx->l3key[i] >= p64 || tctx->l3key[i+1] >= p64);
|
||||
}
|
||||
|
||||
/* Invalidate nonce/aes cache and reset other elements */
|
||||
ctx->__vmac_ctx.cached_nonce[0] = (u64)-1; /* Ensure illegal nonce */
|
||||
ctx->__vmac_ctx.cached_nonce[1] = (u64)0; /* Ensure illegal nonce */
|
||||
ctx->__vmac_ctx.first_block_processed = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vmac_setkey(struct crypto_shash *parent,
|
||||
const u8 *key, unsigned int keylen)
|
||||
{
|
||||
struct vmac_ctx_t *ctx = crypto_shash_ctx(parent);
|
||||
|
||||
if (keylen != VMAC_KEY_LEN) {
|
||||
crypto_shash_set_flags(parent, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return vmac_set_key((u8 *)key, ctx);
|
||||
}
|
||||
|
||||
static int vmac_init(struct shash_desc *pdesc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmac_update(struct shash_desc *pdesc, const u8 *p,
|
||||
unsigned int len)
|
||||
{
|
||||
struct crypto_shash *parent = pdesc->tfm;
|
||||
struct vmac_ctx_t *ctx = crypto_shash_ctx(parent);
|
||||
int expand;
|
||||
int min;
|
||||
|
||||
expand = VMAC_NHBYTES - ctx->partial_size > 0 ?
|
||||
VMAC_NHBYTES - ctx->partial_size : 0;
|
||||
|
||||
min = len < expand ? len : expand;
|
||||
|
||||
memcpy(ctx->partial + ctx->partial_size, p, min);
|
||||
ctx->partial_size += min;
|
||||
|
||||
if (len < expand)
|
||||
return 0;
|
||||
|
||||
vhash_update(ctx->partial, VMAC_NHBYTES, &ctx->__vmac_ctx);
|
||||
ctx->partial_size = 0;
|
||||
|
||||
len -= expand;
|
||||
p += expand;
|
||||
|
||||
if (len % VMAC_NHBYTES) {
|
||||
memcpy(ctx->partial, p + len - (len % VMAC_NHBYTES),
|
||||
len % VMAC_NHBYTES);
|
||||
ctx->partial_size = len % VMAC_NHBYTES;
|
||||
}
|
||||
|
||||
vhash_update(p, len - len % VMAC_NHBYTES, &ctx->__vmac_ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmac_final(struct shash_desc *pdesc, u8 *out)
|
||||
static int vmac_init(struct shash_desc *desc)
|
||||
{
|
||||
struct crypto_shash *parent = pdesc->tfm;
|
||||
struct vmac_ctx_t *ctx = crypto_shash_ctx(parent);
|
||||
vmac_t mac;
|
||||
u8 nonce[16] = {};
|
||||
const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
|
||||
struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||
|
||||
/* vmac() ends up accessing outside the array bounds that
|
||||
* we specify. In appears to access up to the next 2-word
|
||||
* boundary. We'll just be uber cautious and zero the
|
||||
* unwritten bytes in the buffer.
|
||||
*/
|
||||
if (ctx->partial_size) {
|
||||
memset(ctx->partial + ctx->partial_size, 0,
|
||||
VMAC_NHBYTES - ctx->partial_size);
|
||||
dctx->partial_size = 0;
|
||||
dctx->first_block_processed = false;
|
||||
memcpy(dctx->polytmp, tctx->polykey, sizeof(dctx->polytmp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmac_update(struct shash_desc *desc, const u8 *p, unsigned int len)
|
||||
{
|
||||
const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
|
||||
struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||
unsigned int n;
|
||||
|
||||
if (dctx->partial_size) {
|
||||
n = min(len, VMAC_NHBYTES - dctx->partial_size);
|
||||
memcpy(&dctx->partial[dctx->partial_size], p, n);
|
||||
dctx->partial_size += n;
|
||||
p += n;
|
||||
len -= n;
|
||||
if (dctx->partial_size == VMAC_NHBYTES) {
|
||||
vhash_blocks(tctx, dctx, dctx->partial_words, 1);
|
||||
dctx->partial_size = 0;
|
||||
}
|
||||
}
|
||||
mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx);
|
||||
memcpy(out, &mac, sizeof(vmac_t));
|
||||
memzero_explicit(&mac, sizeof(vmac_t));
|
||||
memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx));
|
||||
ctx->partial_size = 0;
|
||||
|
||||
if (len >= VMAC_NHBYTES) {
|
||||
n = round_down(len, VMAC_NHBYTES);
|
||||
/* TODO: 'p' may be misaligned here */
|
||||
vhash_blocks(tctx, dctx, (const __le64 *)p, n / VMAC_NHBYTES);
|
||||
p += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
memcpy(dctx->partial, p, len);
|
||||
dctx->partial_size = len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 vhash_final(const struct vmac_tfm_ctx *tctx,
|
||||
struct vmac_desc_ctx *dctx)
|
||||
{
|
||||
unsigned int partial = dctx->partial_size;
|
||||
u64 ch = dctx->polytmp[0];
|
||||
u64 cl = dctx->polytmp[1];
|
||||
|
||||
/* L1 and L2-hash the final block if needed */
|
||||
if (partial) {
|
||||
/* Zero-pad to next 128-bit boundary */
|
||||
unsigned int n = round_up(partial, 16);
|
||||
u64 rh, rl;
|
||||
|
||||
memset(&dctx->partial[partial], 0, n - partial);
|
||||
nh_16(dctx->partial_words, tctx->nhkey, n / 8, rh, rl);
|
||||
rh &= m62;
|
||||
if (dctx->first_block_processed)
|
||||
poly_step(ch, cl, tctx->polykey[0], tctx->polykey[1],
|
||||
rh, rl);
|
||||
else
|
||||
ADD128(ch, cl, rh, rl);
|
||||
}
|
||||
|
||||
/* L3-hash the 128-bit output of L2-hash */
|
||||
return l3hash(ch, cl, tctx->l3key[0], tctx->l3key[1], partial * 8);
|
||||
}
|
||||
|
||||
static int vmac_final(struct shash_desc *desc, u8 *out)
|
||||
{
|
||||
const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
|
||||
struct vmac_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||
static const u8 nonce[16] = {}; /* TODO: this is insecure */
|
||||
union {
|
||||
u8 bytes[16];
|
||||
__be64 pads[2];
|
||||
} block;
|
||||
int index;
|
||||
u64 hash, pad;
|
||||
|
||||
/* Finish calculating the VHASH of the message */
|
||||
hash = vhash_final(tctx, dctx);
|
||||
|
||||
/* Generate pseudorandom pad by encrypting the nonce */
|
||||
memcpy(&block, nonce, 16);
|
||||
index = block.bytes[15] & 1;
|
||||
block.bytes[15] &= ~1;
|
||||
crypto_cipher_encrypt_one(tctx->cipher, block.bytes, block.bytes);
|
||||
pad = be64_to_cpu(block.pads[index]);
|
||||
|
||||
/* The VMAC is the sum of VHASH and the pseudorandom pad */
|
||||
put_unaligned_le64(hash + pad, out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmac_init_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_cipher *cipher;
|
||||
struct crypto_instance *inst = (void *)tfm->__crt_alg;
|
||||
struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
|
||||
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
|
||||
struct vmac_ctx_t *ctx = crypto_tfm_ctx(tfm);
|
||||
struct vmac_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
|
||||
struct crypto_cipher *cipher;
|
||||
|
||||
cipher = crypto_spawn_cipher(spawn);
|
||||
if (IS_ERR(cipher))
|
||||
return PTR_ERR(cipher);
|
||||
|
||||
ctx->child = cipher;
|
||||
tctx->cipher = cipher;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vmac_exit_tfm(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct vmac_ctx_t *ctx = crypto_tfm_ctx(tfm);
|
||||
crypto_free_cipher(ctx->child);
|
||||
struct vmac_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
crypto_free_cipher(tctx->cipher);
|
||||
}
|
||||
|
||||
static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb)
|
||||
|
@ -655,6 +608,10 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb)
|
|||
if (IS_ERR(alg))
|
||||
return PTR_ERR(alg);
|
||||
|
||||
err = -EINVAL;
|
||||
if (alg->cra_blocksize != 16)
|
||||
goto out_put_alg;
|
||||
|
||||
inst = shash_alloc_instance("vmac", alg);
|
||||
err = PTR_ERR(inst);
|
||||
if (IS_ERR(inst))
|
||||
|
@ -670,11 +627,12 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb)
|
|||
inst->alg.base.cra_blocksize = alg->cra_blocksize;
|
||||
inst->alg.base.cra_alignmask = alg->cra_alignmask;
|
||||
|
||||
inst->alg.digestsize = sizeof(vmac_t);
|
||||
inst->alg.base.cra_ctxsize = sizeof(struct vmac_ctx_t);
|
||||
inst->alg.base.cra_ctxsize = sizeof(struct vmac_tfm_ctx);
|
||||
inst->alg.base.cra_init = vmac_init_tfm;
|
||||
inst->alg.base.cra_exit = vmac_exit_tfm;
|
||||
|
||||
inst->alg.descsize = sizeof(struct vmac_desc_ctx);
|
||||
inst->alg.digestsize = VMAC_TAG_LEN / 8;
|
||||
inst->alg.init = vmac_init;
|
||||
inst->alg.update = vmac_update;
|
||||
inst->alg.final = vmac_final;
|
||||
|
|
209
crypto/zstd.c
Normal file
209
crypto/zstd.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Cryptographic API.
|
||||
*
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/zstd.h>
|
||||
|
||||
|
||||
#define ZSTD_DEF_LEVEL 3
|
||||
|
||||
struct zstd_ctx {
|
||||
ZSTD_CCtx *cctx;
|
||||
ZSTD_DCtx *dctx;
|
||||
void *cwksp;
|
||||
void *dwksp;
|
||||
};
|
||||
|
||||
static ZSTD_parameters zstd_params(void)
|
||||
{
|
||||
return ZSTD_getParams(ZSTD_DEF_LEVEL, 0, 0);
|
||||
}
|
||||
|
||||
static int zstd_comp_init(struct zstd_ctx *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
const ZSTD_parameters params = zstd_params();
|
||||
const size_t wksp_size = ZSTD_CCtxWorkspaceBound(params.cParams);
|
||||
|
||||
ctx->cwksp = vzalloc(wksp_size);
|
||||
if (!ctx->cwksp) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx->cctx = ZSTD_initCCtx(ctx->cwksp, wksp_size);
|
||||
if (!ctx->cctx) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
out_free:
|
||||
vfree(ctx->cwksp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int zstd_decomp_init(struct zstd_ctx *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
const size_t wksp_size = ZSTD_DCtxWorkspaceBound();
|
||||
|
||||
ctx->dwksp = vzalloc(wksp_size);
|
||||
if (!ctx->dwksp) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx->dctx = ZSTD_initDCtx(ctx->dwksp, wksp_size);
|
||||
if (!ctx->dctx) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
out_free:
|
||||
vfree(ctx->dwksp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void zstd_comp_exit(struct zstd_ctx *ctx)
|
||||
{
|
||||
vfree(ctx->cwksp);
|
||||
ctx->cwksp = NULL;
|
||||
ctx->cctx = NULL;
|
||||
}
|
||||
|
||||
static void zstd_decomp_exit(struct zstd_ctx *ctx)
|
||||
{
|
||||
vfree(ctx->dwksp);
|
||||
ctx->dwksp = NULL;
|
||||
ctx->dctx = NULL;
|
||||
}
|
||||
|
||||
static int __zstd_init(void *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = zstd_comp_init(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = zstd_decomp_init(ctx);
|
||||
if (ret)
|
||||
zstd_comp_exit(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int zstd_init(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct zstd_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
return __zstd_init(ctx);
|
||||
}
|
||||
|
||||
static void __zstd_exit(void *ctx)
|
||||
{
|
||||
zstd_comp_exit(ctx);
|
||||
zstd_decomp_exit(ctx);
|
||||
}
|
||||
|
||||
static void zstd_exit(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct zstd_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
__zstd_exit(ctx);
|
||||
}
|
||||
|
||||
static int __zstd_compress(const u8 *src, unsigned int slen,
|
||||
u8 *dst, unsigned int *dlen, void *ctx)
|
||||
{
|
||||
size_t out_len;
|
||||
struct zstd_ctx *zctx = ctx;
|
||||
const ZSTD_parameters params = zstd_params();
|
||||
|
||||
out_len = ZSTD_compressCCtx(zctx->cctx, dst, *dlen, src, slen, params);
|
||||
if (ZSTD_isError(out_len))
|
||||
return -EINVAL;
|
||||
*dlen = out_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zstd_compress(struct crypto_tfm *tfm, const u8 *src,
|
||||
unsigned int slen, u8 *dst, unsigned int *dlen)
|
||||
{
|
||||
struct zstd_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
return __zstd_compress(src, slen, dst, dlen, ctx);
|
||||
}
|
||||
|
||||
static int __zstd_decompress(const u8 *src, unsigned int slen,
|
||||
u8 *dst, unsigned int *dlen, void *ctx)
|
||||
{
|
||||
size_t out_len;
|
||||
struct zstd_ctx *zctx = ctx;
|
||||
|
||||
out_len = ZSTD_decompressDCtx(zctx->dctx, dst, *dlen, src, slen);
|
||||
if (ZSTD_isError(out_len))
|
||||
return -EINVAL;
|
||||
*dlen = out_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zstd_decompress(struct crypto_tfm *tfm, const u8 *src,
|
||||
unsigned int slen, u8 *dst, unsigned int *dlen)
|
||||
{
|
||||
struct zstd_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
return __zstd_decompress(src, slen, dst, dlen, ctx);
|
||||
}
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "zstd",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
|
||||
.cra_ctxsize = sizeof(struct zstd_ctx),
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_init = zstd_init,
|
||||
.cra_exit = zstd_exit,
|
||||
.cra_u = { .compress = {
|
||||
.coa_compress = zstd_compress,
|
||||
.coa_decompress = zstd_decompress } }
|
||||
};
|
||||
|
||||
static int __init zstd_mod_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = crypto_register_alg(&alg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit zstd_mod_fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&alg);
|
||||
}
|
||||
|
||||
module_init(zstd_mod_init);
|
||||
module_exit(zstd_mod_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Zstd Compression Algorithm");
|
||||
MODULE_ALIAS_CRYPTO("zstd");
|
|
@ -124,6 +124,12 @@ void __init acpi_nvs_nosave_s3(void)
|
|||
nvs_nosave_s3 = true;
|
||||
}
|
||||
|
||||
static int __init init_nvs_save_s3(const struct dmi_system_id *d)
|
||||
{
|
||||
nvs_nosave_s3 = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the
|
||||
* user to request that behavior by using the 'acpi_old_suspend_ordering'
|
||||
|
@ -318,6 +324,27 @@ static struct dmi_system_id acpisleep_dmi_table[] __initdata = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = init_nvs_save_s3,
|
||||
.ident = "Asus 1025C",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "1025C"),
|
||||
},
|
||||
},
|
||||
/*
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=189431
|
||||
* Lenovo G50-45 is a platform later than 2012, but needs nvs memory
|
||||
* saving during S3.
|
||||
*/
|
||||
{
|
||||
.callback = init_nvs_save_s3,
|
||||
.ident = "Lenovo G50-45",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "80E3"),
|
||||
},
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -222,11 +222,11 @@ void *removed_alloc(struct device *dev, size_t size, dma_addr_t *handle,
|
|||
bool no_kernel_mapping = dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING,
|
||||
attrs);
|
||||
bool skip_zeroing = dma_get_attr(DMA_ATTR_SKIP_ZEROING, attrs);
|
||||
int pageno;
|
||||
unsigned int pageno;
|
||||
unsigned long order;
|
||||
void *addr = NULL;
|
||||
struct removed_region *dma_mem = dev->removed_mem;
|
||||
int nbits;
|
||||
unsigned int nbits;
|
||||
unsigned int align;
|
||||
|
||||
if (!gfpflags_allow_blocking(gfp))
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
config ZRAM
|
||||
tristate "Compressed RAM block device support"
|
||||
depends on BLOCK && SYSFS && ZSMALLOC
|
||||
select LZO_COMPRESS
|
||||
select LZO_DECOMPRESS
|
||||
depends on BLOCK && SYSFS && ZSMALLOC && CRYPTO
|
||||
select CRYPTO_LZO
|
||||
default n
|
||||
help
|
||||
Creates virtual block devices called /dev/zramX (X = 0, 1, ...).
|
||||
|
@ -13,14 +12,26 @@ config ZRAM
|
|||
It has several use cases, for example: /tmp storage, use as swap
|
||||
disks and maybe many more.
|
||||
|
||||
See zram.txt for more information.
|
||||
See Documentation/blockdev/zram.txt for more information.
|
||||
|
||||
config ZRAM_LZ4_COMPRESS
|
||||
bool "Enable LZ4 algorithm support"
|
||||
depends on ZRAM
|
||||
select LZ4_COMPRESS
|
||||
select LZ4_DECOMPRESS
|
||||
default n
|
||||
config ZRAM_WRITEBACK
|
||||
bool "Write back incompressible page to backing device"
|
||||
depends on ZRAM
|
||||
default n
|
||||
help
|
||||
With incompressible page, there is no memory saving to keep it
|
||||
in memory. Instead, write it out to backing device.
|
||||
For this feature, admin should set up backing device via
|
||||
/sys/block/zramX/backing_dev.
|
||||
|
||||
See Documentation/blockdev/zram.txt for more information.
|
||||
|
||||
config ZRAM_MEMORY_TRACKING
|
||||
bool "Track zRam block status"
|
||||
depends on ZRAM && DEBUG_FS
|
||||
help
|
||||
This option enables LZ4 compression algorithm support. Compression
|
||||
algorithm can be changed using `comp_algorithm' device attribute.
|
||||
With this feature, admin can track the state of allocated blocks
|
||||
of zRAM. Admin could see the information via
|
||||
/sys/kernel/debug/zram/zramX/block_state.
|
||||
|
||||
See Documentation/blockdev/zram.txt for more information.
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
zram-y := zcomp_lzo.o zcomp.o zram_drv.o
|
||||
|
||||
zram-$(CONFIG_ZRAM_LZ4_COMPRESS) += zcomp_lz4.o
|
||||
zram-y := zcomp.o zram_drv.o
|
||||
|
||||
obj-$(CONFIG_ZRAM) += zram.o
|
||||
|
|
|
@ -13,315 +13,233 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/crypto.h>
|
||||
|
||||
#include "zcomp.h"
|
||||
#include "zcomp_lzo.h"
|
||||
#ifdef CONFIG_ZRAM_LZ4_COMPRESS
|
||||
#include "zcomp_lz4.h"
|
||||
|
||||
static const char * const backends[] = {
|
||||
"lzo",
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_LZ4)
|
||||
"lz4",
|
||||
#endif
|
||||
|
||||
/*
|
||||
* single zcomp_strm backend
|
||||
*/
|
||||
struct zcomp_strm_single {
|
||||
struct mutex strm_lock;
|
||||
struct zcomp_strm *zstrm;
|
||||
};
|
||||
|
||||
/*
|
||||
* multi zcomp_strm backend
|
||||
*/
|
||||
struct zcomp_strm_multi {
|
||||
/* protect strm list */
|
||||
spinlock_t strm_lock;
|
||||
/* max possible number of zstrm streams */
|
||||
int max_strm;
|
||||
/* number of available zstrm streams */
|
||||
int avail_strm;
|
||||
/* list of available strms */
|
||||
struct list_head idle_strm;
|
||||
wait_queue_head_t strm_wait;
|
||||
};
|
||||
|
||||
static struct zcomp_backend *backends[] = {
|
||||
&zcomp_lzo,
|
||||
#ifdef CONFIG_ZRAM_LZ4_COMPRESS
|
||||
&zcomp_lz4,
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_DEFLATE)
|
||||
"deflate",
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_LZ4HC)
|
||||
"lz4hc",
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_842)
|
||||
"842",
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_CRYPTO_ZSTD)
|
||||
"zstd",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct zcomp_backend *find_backend(const char *compress)
|
||||
static void zcomp_strm_free(struct zcomp_strm *zstrm)
|
||||
{
|
||||
int i = 0;
|
||||
while (backends[i]) {
|
||||
if (sysfs_streq(compress, backends[i]->name))
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return backends[i];
|
||||
}
|
||||
|
||||
static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
|
||||
{
|
||||
if (zstrm->private)
|
||||
comp->backend->destroy(zstrm->private);
|
||||
if (!IS_ERR_OR_NULL(zstrm->tfm))
|
||||
crypto_free_comp(zstrm->tfm);
|
||||
free_pages((unsigned long)zstrm->buffer, 1);
|
||||
kfree(zstrm);
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate new zcomp_strm structure with ->private initialized by
|
||||
* allocate new zcomp_strm structure with ->tfm initialized by
|
||||
* backend, return NULL on error
|
||||
*/
|
||||
static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_NOIO);
|
||||
struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
|
||||
if (!zstrm)
|
||||
return NULL;
|
||||
|
||||
zstrm->private = comp->backend->create();
|
||||
zstrm->tfm = crypto_alloc_comp(comp->name, 0, 0);
|
||||
/*
|
||||
* allocate 2 pages. 1 for compressed data, plus 1 extra for the
|
||||
* case when compressed size is larger than the original one
|
||||
*/
|
||||
zstrm->buffer = (void *)__get_free_pages(GFP_NOIO | __GFP_ZERO, 1);
|
||||
if (!zstrm->private || !zstrm->buffer) {
|
||||
zcomp_strm_free(comp, zstrm);
|
||||
zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
|
||||
if (IS_ERR_OR_NULL(zstrm->tfm) || !zstrm->buffer) {
|
||||
zcomp_strm_free(zstrm);
|
||||
zstrm = NULL;
|
||||
}
|
||||
return zstrm;
|
||||
}
|
||||
|
||||
/*
|
||||
* get idle zcomp_strm or wait until other process release
|
||||
* (zcomp_strm_release()) one for us
|
||||
*/
|
||||
static struct zcomp_strm *zcomp_strm_multi_find(struct zcomp *comp)
|
||||
bool zcomp_available_algorithm(const char *comp)
|
||||
{
|
||||
struct zcomp_strm_multi *zs = comp->stream;
|
||||
struct zcomp_strm *zstrm;
|
||||
int i = 0;
|
||||
|
||||
while (1) {
|
||||
spin_lock(&zs->strm_lock);
|
||||
if (!list_empty(&zs->idle_strm)) {
|
||||
zstrm = list_entry(zs->idle_strm.next,
|
||||
struct zcomp_strm, list);
|
||||
list_del(&zstrm->list);
|
||||
spin_unlock(&zs->strm_lock);
|
||||
return zstrm;
|
||||
}
|
||||
/* zstrm streams limit reached, wait for idle stream */
|
||||
if (zs->avail_strm >= zs->max_strm) {
|
||||
spin_unlock(&zs->strm_lock);
|
||||
wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
|
||||
continue;
|
||||
}
|
||||
/* allocate new zstrm stream */
|
||||
zs->avail_strm++;
|
||||
spin_unlock(&zs->strm_lock);
|
||||
|
||||
zstrm = zcomp_strm_alloc(comp);
|
||||
if (!zstrm) {
|
||||
spin_lock(&zs->strm_lock);
|
||||
zs->avail_strm--;
|
||||
spin_unlock(&zs->strm_lock);
|
||||
wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return zstrm;
|
||||
}
|
||||
|
||||
/* add stream back to idle list and wake up waiter or free the stream */
|
||||
static void zcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm)
|
||||
{
|
||||
struct zcomp_strm_multi *zs = comp->stream;
|
||||
|
||||
spin_lock(&zs->strm_lock);
|
||||
if (zs->avail_strm <= zs->max_strm) {
|
||||
list_add(&zstrm->list, &zs->idle_strm);
|
||||
spin_unlock(&zs->strm_lock);
|
||||
wake_up(&zs->strm_wait);
|
||||
return;
|
||||
while (backends[i]) {
|
||||
if (sysfs_streq(comp, backends[i]))
|
||||
return true;
|
||||
i++;
|
||||
}
|
||||
|
||||
zs->avail_strm--;
|
||||
spin_unlock(&zs->strm_lock);
|
||||
zcomp_strm_free(comp, zstrm);
|
||||
}
|
||||
|
||||
/* change max_strm limit */
|
||||
static bool zcomp_strm_multi_set_max_streams(struct zcomp *comp, int num_strm)
|
||||
{
|
||||
struct zcomp_strm_multi *zs = comp->stream;
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
spin_lock(&zs->strm_lock);
|
||||
zs->max_strm = num_strm;
|
||||
/*
|
||||
* if user has lowered the limit and there are idle streams,
|
||||
* immediately free as much streams (and memory) as we can.
|
||||
* Crypto does not ignore a trailing new line symbol,
|
||||
* so make sure you don't supply a string containing
|
||||
* one.
|
||||
* This also means that we permit zcomp initialisation
|
||||
* with any compressing algorithm known to crypto api.
|
||||
*/
|
||||
while (zs->avail_strm > num_strm && !list_empty(&zs->idle_strm)) {
|
||||
zstrm = list_entry(zs->idle_strm.next,
|
||||
struct zcomp_strm, list);
|
||||
list_del(&zstrm->list);
|
||||
zcomp_strm_free(comp, zstrm);
|
||||
zs->avail_strm--;
|
||||
}
|
||||
spin_unlock(&zs->strm_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void zcomp_strm_multi_destroy(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_multi *zs = comp->stream;
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
while (!list_empty(&zs->idle_strm)) {
|
||||
zstrm = list_entry(zs->idle_strm.next,
|
||||
struct zcomp_strm, list);
|
||||
list_del(&zstrm->list);
|
||||
zcomp_strm_free(comp, zstrm);
|
||||
}
|
||||
kfree(zs);
|
||||
}
|
||||
|
||||
static int zcomp_strm_multi_create(struct zcomp *comp, int max_strm)
|
||||
{
|
||||
struct zcomp_strm *zstrm;
|
||||
struct zcomp_strm_multi *zs;
|
||||
|
||||
comp->destroy = zcomp_strm_multi_destroy;
|
||||
comp->strm_find = zcomp_strm_multi_find;
|
||||
comp->strm_release = zcomp_strm_multi_release;
|
||||
comp->set_max_streams = zcomp_strm_multi_set_max_streams;
|
||||
zs = kmalloc(sizeof(struct zcomp_strm_multi), GFP_KERNEL);
|
||||
if (!zs)
|
||||
return -ENOMEM;
|
||||
|
||||
comp->stream = zs;
|
||||
spin_lock_init(&zs->strm_lock);
|
||||
INIT_LIST_HEAD(&zs->idle_strm);
|
||||
init_waitqueue_head(&zs->strm_wait);
|
||||
zs->max_strm = max_strm;
|
||||
zs->avail_strm = 1;
|
||||
|
||||
zstrm = zcomp_strm_alloc(comp);
|
||||
if (!zstrm) {
|
||||
kfree(zs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
list_add(&zstrm->list, &zs->idle_strm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_single *zs = comp->stream;
|
||||
mutex_lock(&zs->strm_lock);
|
||||
return zs->zstrm;
|
||||
}
|
||||
|
||||
static void zcomp_strm_single_release(struct zcomp *comp,
|
||||
struct zcomp_strm *zstrm)
|
||||
{
|
||||
struct zcomp_strm_single *zs = comp->stream;
|
||||
mutex_unlock(&zs->strm_lock);
|
||||
}
|
||||
|
||||
static bool zcomp_strm_single_set_max_streams(struct zcomp *comp, int num_strm)
|
||||
{
|
||||
/* zcomp_strm_single support only max_comp_streams == 1 */
|
||||
return false;
|
||||
}
|
||||
|
||||
static void zcomp_strm_single_destroy(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_single *zs = comp->stream;
|
||||
zcomp_strm_free(comp, zs->zstrm);
|
||||
kfree(zs);
|
||||
}
|
||||
|
||||
static int zcomp_strm_single_create(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_single *zs;
|
||||
|
||||
comp->destroy = zcomp_strm_single_destroy;
|
||||
comp->strm_find = zcomp_strm_single_find;
|
||||
comp->strm_release = zcomp_strm_single_release;
|
||||
comp->set_max_streams = zcomp_strm_single_set_max_streams;
|
||||
zs = kmalloc(sizeof(struct zcomp_strm_single), GFP_KERNEL);
|
||||
if (!zs)
|
||||
return -ENOMEM;
|
||||
|
||||
comp->stream = zs;
|
||||
mutex_init(&zs->strm_lock);
|
||||
zs->zstrm = zcomp_strm_alloc(comp);
|
||||
if (!zs->zstrm) {
|
||||
kfree(zs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
return crypto_has_comp(comp, 0, 0) == 1;
|
||||
}
|
||||
|
||||
/* show available compressors */
|
||||
ssize_t zcomp_available_show(const char *comp, char *buf)
|
||||
{
|
||||
bool known_algorithm = false;
|
||||
ssize_t sz = 0;
|
||||
int i = 0;
|
||||
|
||||
while (backends[i]) {
|
||||
if (!strcmp(comp, backends[i]->name))
|
||||
for (; backends[i]; i++) {
|
||||
if (!strcmp(comp, backends[i])) {
|
||||
known_algorithm = true;
|
||||
sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
|
||||
"[%s] ", backends[i]->name);
|
||||
else
|
||||
"[%s] ", backends[i]);
|
||||
} else {
|
||||
sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
|
||||
"%s ", backends[i]->name);
|
||||
i++;
|
||||
"%s ", backends[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Out-of-tree module known to crypto api or a missing
|
||||
* entry in `backends'.
|
||||
*/
|
||||
if (!known_algorithm && crypto_has_comp(comp, 0, 0) == 1)
|
||||
sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
|
||||
"[%s] ", comp);
|
||||
|
||||
sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
|
||||
return sz;
|
||||
}
|
||||
|
||||
bool zcomp_available_algorithm(const char *comp)
|
||||
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
|
||||
{
|
||||
return find_backend(comp) != NULL;
|
||||
return *get_cpu_ptr(comp->stream);
|
||||
}
|
||||
|
||||
bool zcomp_set_max_streams(struct zcomp *comp, int num_strm)
|
||||
void zcomp_stream_put(struct zcomp *comp)
|
||||
{
|
||||
return comp->set_max_streams(comp, num_strm);
|
||||
put_cpu_ptr(comp->stream);
|
||||
}
|
||||
|
||||
struct zcomp_strm *zcomp_strm_find(struct zcomp *comp)
|
||||
int zcomp_compress(struct zcomp_strm *zstrm,
|
||||
const void *src, unsigned int *dst_len)
|
||||
{
|
||||
return comp->strm_find(comp);
|
||||
/*
|
||||
* Our dst memory (zstrm->buffer) is always `2 * PAGE_SIZE' sized
|
||||
* because sometimes we can endup having a bigger compressed data
|
||||
* due to various reasons: for example compression algorithms tend
|
||||
* to add some padding to the compressed buffer. Speaking of padding,
|
||||
* comp algorithm `842' pads the compressed length to multiple of 8
|
||||
* and returns -ENOSP when the dst memory is not big enough, which
|
||||
* is not something that ZRAM wants to see. We can handle the
|
||||
* `compressed_size > PAGE_SIZE' case easily in ZRAM, but when we
|
||||
* receive -ERRNO from the compressing backend we can't help it
|
||||
* anymore. To make `842' happy we need to tell the exact size of
|
||||
* the dst buffer, zram_drv will take care of the fact that
|
||||
* compressed buffer is too big.
|
||||
*/
|
||||
*dst_len = PAGE_SIZE * 2;
|
||||
|
||||
return crypto_comp_compress(zstrm->tfm,
|
||||
src, PAGE_SIZE,
|
||||
zstrm->buffer, dst_len);
|
||||
}
|
||||
|
||||
void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm)
|
||||
int zcomp_decompress(struct zcomp_strm *zstrm,
|
||||
const void *src, unsigned int src_len, void *dst)
|
||||
{
|
||||
comp->strm_release(comp, zstrm);
|
||||
unsigned int dst_len = PAGE_SIZE;
|
||||
|
||||
return crypto_comp_decompress(zstrm->tfm,
|
||||
src, src_len,
|
||||
dst, &dst_len);
|
||||
}
|
||||
|
||||
int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
|
||||
const unsigned char *src, size_t *dst_len)
|
||||
static int __zcomp_cpu_notifier(struct zcomp *comp,
|
||||
unsigned long action, unsigned long cpu)
|
||||
{
|
||||
return comp->backend->compress(src, zstrm->buffer, dst_len,
|
||||
zstrm->private);
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
switch (action) {
|
||||
case CPU_UP_PREPARE:
|
||||
if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
|
||||
break;
|
||||
zstrm = zcomp_strm_alloc(comp);
|
||||
if (IS_ERR_OR_NULL(zstrm)) {
|
||||
pr_err("Can't allocate a compression stream\n");
|
||||
return NOTIFY_BAD;
|
||||
}
|
||||
*per_cpu_ptr(comp->stream, cpu) = zstrm;
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
case CPU_UP_CANCELED:
|
||||
zstrm = *per_cpu_ptr(comp->stream, cpu);
|
||||
if (!IS_ERR_OR_NULL(zstrm))
|
||||
zcomp_strm_free(zstrm);
|
||||
*per_cpu_ptr(comp->stream, cpu) = NULL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
|
||||
size_t src_len, unsigned char *dst)
|
||||
static int zcomp_cpu_notifier(struct notifier_block *nb,
|
||||
unsigned long action, void *pcpu)
|
||||
{
|
||||
return comp->backend->decompress(src, src_len, dst);
|
||||
unsigned long cpu = (unsigned long)pcpu;
|
||||
struct zcomp *comp = container_of(nb, typeof(*comp), notifier);
|
||||
|
||||
return __zcomp_cpu_notifier(comp, action, cpu);
|
||||
}
|
||||
|
||||
static int zcomp_init(struct zcomp *comp)
|
||||
{
|
||||
unsigned long cpu;
|
||||
int ret;
|
||||
|
||||
comp->notifier.notifier_call = zcomp_cpu_notifier;
|
||||
|
||||
comp->stream = alloc_percpu(struct zcomp_strm *);
|
||||
if (!comp->stream)
|
||||
return -ENOMEM;
|
||||
|
||||
cpu_notifier_register_begin();
|
||||
for_each_online_cpu(cpu) {
|
||||
ret = __zcomp_cpu_notifier(comp, CPU_UP_PREPARE, cpu);
|
||||
if (ret == NOTIFY_BAD)
|
||||
goto cleanup;
|
||||
}
|
||||
__register_cpu_notifier(&comp->notifier);
|
||||
cpu_notifier_register_done();
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
for_each_online_cpu(cpu)
|
||||
__zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
|
||||
cpu_notifier_register_done();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void zcomp_destroy(struct zcomp *comp)
|
||||
{
|
||||
comp->destroy(comp);
|
||||
unsigned long cpu;
|
||||
|
||||
cpu_notifier_register_begin();
|
||||
for_each_online_cpu(cpu)
|
||||
__zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
|
||||
__unregister_cpu_notifier(&comp->notifier);
|
||||
cpu_notifier_register_done();
|
||||
|
||||
free_percpu(comp->stream);
|
||||
kfree(comp);
|
||||
}
|
||||
|
||||
|
@ -331,27 +249,22 @@ void zcomp_destroy(struct zcomp *comp)
|
|||
* backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
|
||||
* if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
|
||||
* case of allocation error, or any other error potentially
|
||||
* returned by functions zcomp_strm_{multi,single}_create.
|
||||
* returned by zcomp_init().
|
||||
*/
|
||||
struct zcomp *zcomp_create(const char *compress, int max_strm)
|
||||
struct zcomp *zcomp_create(const char *compress)
|
||||
{
|
||||
struct zcomp *comp;
|
||||
struct zcomp_backend *backend;
|
||||
int error;
|
||||
|
||||
backend = find_backend(compress);
|
||||
if (!backend)
|
||||
if (!zcomp_available_algorithm(compress))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
|
||||
if (!comp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
comp->backend = backend;
|
||||
if (max_strm > 1)
|
||||
error = zcomp_strm_multi_create(comp, max_strm);
|
||||
else
|
||||
error = zcomp_strm_single_create(comp);
|
||||
comp->name = compress;
|
||||
error = zcomp_init(comp);
|
||||
if (error) {
|
||||
kfree(comp);
|
||||
return ERR_PTR(error);
|
||||
|
|
|
@ -10,60 +10,34 @@
|
|||
#ifndef _ZCOMP_H_
|
||||
#define _ZCOMP_H_
|
||||
|
||||
#include <linux/mutex.h>
|
||||
|
||||
struct zcomp_strm {
|
||||
/* compression/decompression buffer */
|
||||
void *buffer;
|
||||
/*
|
||||
* The private data of the compression stream, only compression
|
||||
* stream backend can touch this (e.g. compression algorithm
|
||||
* working memory)
|
||||
*/
|
||||
void *private;
|
||||
/* used in multi stream backend, protected by backend strm_lock */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/* static compression backend */
|
||||
struct zcomp_backend {
|
||||
int (*compress)(const unsigned char *src, unsigned char *dst,
|
||||
size_t *dst_len, void *private);
|
||||
|
||||
int (*decompress)(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst);
|
||||
|
||||
void *(*create)(void);
|
||||
void (*destroy)(void *private);
|
||||
|
||||
const char *name;
|
||||
struct crypto_comp *tfm;
|
||||
};
|
||||
|
||||
/* dynamic per-device compression frontend */
|
||||
struct zcomp {
|
||||
void *stream;
|
||||
struct zcomp_backend *backend;
|
||||
struct zcomp_strm * __percpu *stream;
|
||||
struct notifier_block notifier;
|
||||
|
||||
struct zcomp_strm *(*strm_find)(struct zcomp *comp);
|
||||
void (*strm_release)(struct zcomp *comp, struct zcomp_strm *zstrm);
|
||||
bool (*set_max_streams)(struct zcomp *comp, int num_strm);
|
||||
void (*destroy)(struct zcomp *comp);
|
||||
const char *name;
|
||||
};
|
||||
|
||||
ssize_t zcomp_available_show(const char *comp, char *buf);
|
||||
bool zcomp_available_algorithm(const char *comp);
|
||||
|
||||
struct zcomp *zcomp_create(const char *comp, int max_strm);
|
||||
struct zcomp *zcomp_create(const char *comp);
|
||||
void zcomp_destroy(struct zcomp *comp);
|
||||
|
||||
struct zcomp_strm *zcomp_strm_find(struct zcomp *comp);
|
||||
void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm);
|
||||
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp);
|
||||
void zcomp_stream_put(struct zcomp *comp);
|
||||
|
||||
int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
|
||||
const unsigned char *src, size_t *dst_len);
|
||||
int zcomp_compress(struct zcomp_strm *zstrm,
|
||||
const void *src, unsigned int *dst_len);
|
||||
|
||||
int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
|
||||
size_t src_len, unsigned char *dst);
|
||||
int zcomp_decompress(struct zcomp_strm *zstrm,
|
||||
const void *src, unsigned int src_len, void *dst);
|
||||
|
||||
bool zcomp_set_max_streams(struct zcomp *comp, int num_strm);
|
||||
#endif /* _ZCOMP_H_ */
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/lz4.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include "zcomp_lz4.h"
|
||||
|
||||
static void *zcomp_lz4_create(void)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
/*
|
||||
* This function can be called in swapout/fs write path
|
||||
* so we can't use GFP_FS|IO. And it assumes we already
|
||||
* have at least one stream in zram initialization so we
|
||||
* don't do best effort to allocate more stream in here.
|
||||
* A default stream will work well without further multiple
|
||||
* streams. That's why we use NORETRY | NOWARN.
|
||||
*/
|
||||
ret = kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
|
||||
__GFP_NOWARN);
|
||||
if (!ret)
|
||||
ret = __vmalloc(LZ4_MEM_COMPRESS,
|
||||
GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
|
||||
__GFP_ZERO | __GFP_HIGHMEM,
|
||||
PAGE_KERNEL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void zcomp_lz4_destroy(void *private)
|
||||
{
|
||||
kvfree(private);
|
||||
}
|
||||
|
||||
static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
|
||||
size_t *dst_len, void *private)
|
||||
{
|
||||
/* return : Success if return 0 */
|
||||
return lz4_compress(src, PAGE_SIZE, dst, dst_len, private);
|
||||
}
|
||||
|
||||
static int zcomp_lz4_decompress(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst)
|
||||
{
|
||||
size_t dst_len = PAGE_SIZE;
|
||||
/* return : Success if return 0 */
|
||||
return lz4_decompress_unknownoutputsize(src, src_len, dst, &dst_len);
|
||||
}
|
||||
|
||||
struct zcomp_backend zcomp_lz4 = {
|
||||
.compress = zcomp_lz4_compress,
|
||||
.decompress = zcomp_lz4_decompress,
|
||||
.create = zcomp_lz4_create,
|
||||
.destroy = zcomp_lz4_destroy,
|
||||
.name = "lz4",
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _ZCOMP_LZ4_H_
|
||||
#define _ZCOMP_LZ4_H_
|
||||
|
||||
#include "zcomp.h"
|
||||
|
||||
extern struct zcomp_backend zcomp_lz4;
|
||||
|
||||
#endif /* _ZCOMP_LZ4_H_ */
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/lzo.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include "zcomp_lzo.h"
|
||||
|
||||
static void *lzo_create(void)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
/*
|
||||
* This function can be called in swapout/fs write path
|
||||
* so we can't use GFP_FS|IO. And it assumes we already
|
||||
* have at least one stream in zram initialization so we
|
||||
* don't do best effort to allocate more stream in here.
|
||||
* A default stream will work well without further multiple
|
||||
* streams. That's why we use NORETRY | NOWARN.
|
||||
*/
|
||||
ret = kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
|
||||
__GFP_NOWARN);
|
||||
if (!ret)
|
||||
ret = __vmalloc(LZO1X_MEM_COMPRESS,
|
||||
GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
|
||||
__GFP_ZERO | __GFP_HIGHMEM,
|
||||
PAGE_KERNEL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lzo_destroy(void *private)
|
||||
{
|
||||
kvfree(private);
|
||||
}
|
||||
|
||||
static int lzo_compress(const unsigned char *src, unsigned char *dst,
|
||||
size_t *dst_len, void *private)
|
||||
{
|
||||
int ret = lzo1x_1_compress(src, PAGE_SIZE, dst, dst_len, private);
|
||||
return ret == LZO_E_OK ? 0 : ret;
|
||||
}
|
||||
|
||||
static int lzo_decompress(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst)
|
||||
{
|
||||
size_t dst_len = PAGE_SIZE;
|
||||
int ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
|
||||
return ret == LZO_E_OK ? 0 : ret;
|
||||
}
|
||||
|
||||
struct zcomp_backend zcomp_lzo = {
|
||||
.compress = lzo_compress,
|
||||
.decompress = lzo_decompress,
|
||||
.create = lzo_create,
|
||||
.destroy = lzo_destroy,
|
||||
.name = "lzo",
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _ZCOMP_LZO_H_
|
||||
#define _ZCOMP_LZO_H_
|
||||
|
||||
#include "zcomp.h"
|
||||
|
||||
extern struct zcomp_backend zcomp_lzo;
|
||||
|
||||
#endif /* _ZCOMP_LZO_H_ */
|
File diff suppressed because it is too large
Load diff
|
@ -15,8 +15,9 @@
|
|||
#ifndef _ZRAM_DRV_H_
|
||||
#define _ZRAM_DRV_H_
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/zsmalloc.h>
|
||||
#include <linux/crypto.h>
|
||||
|
||||
#include "zcomp.h"
|
||||
|
||||
|
@ -59,9 +60,11 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
|
|||
|
||||
/* Flags for zram pages (table[page_no].value) */
|
||||
enum zram_pageflags {
|
||||
/* Page consists entirely of zeros */
|
||||
ZRAM_ZERO = ZRAM_FLAG_SHIFT,
|
||||
ZRAM_ACCESS, /* page is now accessed */
|
||||
/* zram slot is locked */
|
||||
ZRAM_LOCK = ZRAM_FLAG_SHIFT,
|
||||
ZRAM_SAME, /* Page consists the same element */
|
||||
ZRAM_WB, /* page is stored on backing_device */
|
||||
ZRAM_HUGE, /* Incompressible page */
|
||||
|
||||
__NR_ZRAM_PAGEFLAGS,
|
||||
};
|
||||
|
@ -70,8 +73,14 @@ enum zram_pageflags {
|
|||
|
||||
/* Allocated for each disk page */
|
||||
struct zram_table_entry {
|
||||
unsigned long handle;
|
||||
union {
|
||||
unsigned long handle;
|
||||
unsigned long element;
|
||||
};
|
||||
unsigned long value;
|
||||
#ifdef CONFIG_ZRAM_MEMORY_TRACKING
|
||||
ktime_t ac_time;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct zram_stats {
|
||||
|
@ -82,18 +91,16 @@ struct zram_stats {
|
|||
atomic64_t failed_writes; /* can happen when memory is too low */
|
||||
atomic64_t invalid_io; /* non-page-aligned I/O requests */
|
||||
atomic64_t notify_free; /* no. of swap slot free notifications */
|
||||
atomic64_t zero_pages; /* no. of zero filled pages */
|
||||
atomic64_t same_pages; /* no. of same element filled pages */
|
||||
atomic64_t huge_pages; /* no. of huge pages */
|
||||
atomic64_t pages_stored; /* no. of pages currently stored */
|
||||
atomic_long_t max_used_pages; /* no. of maximum pages stored */
|
||||
};
|
||||
|
||||
struct zram_meta {
|
||||
struct zram_table_entry *table;
|
||||
struct zs_pool *mem_pool;
|
||||
atomic64_t writestall; /* no. of write slow paths */
|
||||
};
|
||||
|
||||
struct zram {
|
||||
struct zram_meta *meta;
|
||||
struct zram_table_entry *table;
|
||||
struct zs_pool *mem_pool;
|
||||
struct zcomp *comp;
|
||||
struct gendisk *disk;
|
||||
/* Prevent concurrent execution of device init */
|
||||
|
@ -102,21 +109,28 @@ struct zram {
|
|||
* the number of pages zram can consume for storing compressed data
|
||||
*/
|
||||
unsigned long limit_pages;
|
||||
int max_comp_streams;
|
||||
|
||||
struct zram_stats stats;
|
||||
atomic_t refcount; /* refcount for zram_meta */
|
||||
/* wait all IO under all of cpu are done */
|
||||
wait_queue_head_t io_done;
|
||||
/*
|
||||
* This is the limit on amount of *uncompressed* worth of data
|
||||
* we can store in a disk.
|
||||
*/
|
||||
u64 disksize; /* bytes */
|
||||
char compressor[10];
|
||||
char compressor[CRYPTO_MAX_ALG_NAME];
|
||||
/*
|
||||
* zram is claimed so open request will be failed
|
||||
*/
|
||||
bool claim; /* Protected by bdev->bd_mutex */
|
||||
#ifdef CONFIG_ZRAM_WRITEBACK
|
||||
struct file *backing_dev;
|
||||
struct block_device *bdev;
|
||||
unsigned int old_block_size;
|
||||
unsigned long *bitmap;
|
||||
unsigned long nr_pages;
|
||||
spinlock_t bitmap_lock;
|
||||
#endif
|
||||
#ifdef CONFIG_ZRAM_MEMORY_TRACKING
|
||||
struct dentry *debugfs_dir;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -68,16 +68,6 @@
|
|||
#define FASTRPC_CTX_MAGIC (0xbeeddeed)
|
||||
#define FASTRPC_CTX_MAX (256)
|
||||
#define FASTRPC_CTXID_MASK (0xFF0)
|
||||
#define NUM_DEVICES 2 /* adsprpc-smd, adsprpc-smd-secure */
|
||||
#define MINOR_NUM_DEV 0
|
||||
#define MINOR_NUM_SECURE_DEV 1
|
||||
#define NON_SECURE_CHANNEL 0
|
||||
#define SECURE_CHANNEL 1
|
||||
|
||||
#define ADSP_DOMAIN_ID (0)
|
||||
#define MDSP_DOMAIN_ID (1)
|
||||
#define SDSP_DOMAIN_ID (2)
|
||||
#define CDSP_DOMAIN_ID (3)
|
||||
|
||||
#define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0)
|
||||
|
||||
|
@ -242,8 +232,6 @@ struct fastrpc_channel_ctx {
|
|||
int ramdumpenabled;
|
||||
void *remoteheap_ramdump_dev;
|
||||
struct fastrpc_glink_info link;
|
||||
/* Indicates, if channel is restricted to secure node only */
|
||||
int secure;
|
||||
};
|
||||
|
||||
struct fastrpc_apps {
|
||||
|
@ -317,8 +305,6 @@ struct fastrpc_file {
|
|||
struct fastrpc_perf perf;
|
||||
struct dentry *debugfs_file;
|
||||
struct mutex map_mutex;
|
||||
/* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */
|
||||
int dev_minor;
|
||||
};
|
||||
|
||||
static struct fastrpc_apps gfa;
|
||||
|
@ -1582,11 +1568,7 @@ static void fastrpc_init(struct fastrpc_apps *me)
|
|||
init_completion(&me->channel[i].work);
|
||||
init_completion(&me->channel[i].workport);
|
||||
me->channel[i].sesscount = 0;
|
||||
/* All channels are secure by default except CDSP */
|
||||
me->channel[i].secure = SECURE_CHANNEL;
|
||||
}
|
||||
/* Set CDSP channel to non secure */
|
||||
me->channel[CDSP_DOMAIN_ID].secure = NON_SECURE_CHANNEL;
|
||||
}
|
||||
|
||||
static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl);
|
||||
|
@ -2511,9 +2493,6 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
|
|||
len += scnprintf(fileinfo + len,
|
||||
DEBUGFS_SIZE - len, "%s\n\n",
|
||||
chan->name);
|
||||
len += scnprintf(fileinfo + len,
|
||||
DEBUGFS_SIZE - len, "%s %d\n",
|
||||
"secure:", chan->secure);
|
||||
len += scnprintf(fileinfo + len,
|
||||
DEBUGFS_SIZE - len, "%s %d\n",
|
||||
"sesscount:", chan->sesscount);
|
||||
|
@ -2542,9 +2521,6 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
|
|||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%s %d\n\n",
|
||||
"SSRCOUNT:", fl->ssrcount);
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%s %d\n\n",
|
||||
"DEV_MINOR:", fl->dev_minor);
|
||||
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
|
||||
"%s\n",
|
||||
"LIST OF BUFS:");
|
||||
|
@ -2682,19 +2658,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
|
|||
struct fastrpc_file *fl = NULL;
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
|
||||
/*
|
||||
* Indicates the device node opened
|
||||
* MINOR_NUM_DEV or MINOR_NUM_SECURE_DEV
|
||||
*/
|
||||
int dev_minor = MINOR(inode->i_rdev);
|
||||
|
||||
VERIFY(err, ((dev_minor == MINOR_NUM_DEV) ||
|
||||
(dev_minor == MINOR_NUM_SECURE_DEV)));
|
||||
if (err) {
|
||||
pr_err("adsprpc: Invalid dev minor num %d\n", dev_minor);
|
||||
return err;
|
||||
}
|
||||
|
||||
VERIFY(err, NULL != (fl = kzalloc(sizeof(*fl), GFP_KERNEL)));
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -2709,8 +2672,6 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
|
|||
fl->apps = me;
|
||||
fl->mode = FASTRPC_MODE_SERIAL;
|
||||
fl->cid = -1;
|
||||
fl->dev_minor = dev_minor;
|
||||
|
||||
if (debugfs_file != NULL)
|
||||
fl->debugfs_file = debugfs_file;
|
||||
memset(&fl->perf, 0, sizeof(fl->perf));
|
||||
|
@ -2735,23 +2696,6 @@ static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info)
|
|||
VERIFY(err, cid < NUM_CHANNELS);
|
||||
if (err)
|
||||
goto bail;
|
||||
/* Check to see if the device node is non-secure */
|
||||
if (fl->dev_minor == MINOR_NUM_DEV) {
|
||||
/*
|
||||
* For non secure device node check and make sure that
|
||||
* the channel allows non-secure access
|
||||
* If not, bail. Session will not start.
|
||||
* cid will remain -1 and client will not be able to
|
||||
* invoke any other methods without failure
|
||||
*/
|
||||
if (fl->apps->channel[cid].secure == SECURE_CHANNEL) {
|
||||
err = -EPERM;
|
||||
pr_err("adsprpc: GetInfo failed dev %d, cid %d, secure %d\n",
|
||||
fl->dev_minor, cid,
|
||||
fl->apps->channel[cid].secure);
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
fl->cid = cid;
|
||||
fl->ssrcount = fl->apps->channel[cid].ssrcount;
|
||||
VERIFY(err, !fastrpc_session_alloc_locked(
|
||||
|
@ -3150,41 +3094,12 @@ bail:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void configure_secure_channels(uint32_t secure_domains)
|
||||
{
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
int ii = 0;
|
||||
/*
|
||||
* secure_domains contains the bitmask of the secure channels
|
||||
* Bit 0 - ADSP
|
||||
* Bit 1 - MDSP
|
||||
* Bit 2 - SLPI
|
||||
* Bit 3 - CDSP
|
||||
*/
|
||||
for (ii = ADSP_DOMAIN_ID; ii <= CDSP_DOMAIN_ID; ++ii) {
|
||||
int secure = (secure_domains >> ii) & 0x01;
|
||||
|
||||
me->channel[ii].secure = secure;
|
||||
}
|
||||
}
|
||||
|
||||
static int fastrpc_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err = 0;
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
struct device *dev = &pdev->dev;
|
||||
uint32_t secure_domains;
|
||||
|
||||
if (of_get_property(dev->of_node,
|
||||
"qcom,secure-domains", NULL) != NULL) {
|
||||
VERIFY(err, !of_property_read_u32(dev->of_node,
|
||||
"qcom,secure-domains",
|
||||
&secure_domains));
|
||||
if (!err)
|
||||
configure_secure_channels(secure_domains);
|
||||
else
|
||||
pr_info("adsprpc: unable to read the domain configuration from dts\n");
|
||||
}
|
||||
if (of_device_is_compatible(dev->of_node,
|
||||
"qcom,msm-fastrpc-compute-cb"))
|
||||
return fastrpc_cb_probe(dev);
|
||||
|
@ -3259,7 +3174,6 @@ static int __init fastrpc_device_init(void)
|
|||
{
|
||||
struct fastrpc_apps *me = &gfa;
|
||||
struct device *dev = NULL;
|
||||
struct device *secure_dev = NULL;
|
||||
int err = 0, i;
|
||||
|
||||
memset(me, 0, sizeof(*me));
|
||||
|
@ -3276,7 +3190,7 @@ static int __init fastrpc_device_init(void)
|
|||
cdev_init(&me->cdev, &fops);
|
||||
me->cdev.owner = THIS_MODULE;
|
||||
VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0),
|
||||
NUM_DEVICES));
|
||||
1));
|
||||
if (err)
|
||||
goto cdev_init_bail;
|
||||
me->class = class_create(THIS_MODULE, "fastrpc");
|
||||
|
@ -3284,29 +3198,14 @@ static int __init fastrpc_device_init(void)
|
|||
if (err)
|
||||
goto class_create_bail;
|
||||
me->compat = (NULL == fops.compat_ioctl) ? 0 : 1;
|
||||
/*
|
||||
* Create devices and register with sysfs
|
||||
* Create first device with minor number 0
|
||||
*/
|
||||
dev = device_create(me->class, NULL,
|
||||
MKDEV(MAJOR(me->dev_no), MINOR_NUM_DEV),
|
||||
NULL, DEVICE_NAME);
|
||||
MKDEV(MAJOR(me->dev_no), 0),
|
||||
NULL, gcinfo[0].name);
|
||||
VERIFY(err, !IS_ERR_OR_NULL(dev));
|
||||
if (err)
|
||||
goto device_create_bail;
|
||||
|
||||
/* Create secure device with minor number for secure device */
|
||||
secure_dev = device_create(me->class, NULL,
|
||||
MKDEV(MAJOR(me->dev_no), MINOR_NUM_SECURE_DEV),
|
||||
NULL, DEVICE_NAME_SECURE);
|
||||
VERIFY(err, !IS_ERR_OR_NULL(secure_dev));
|
||||
if (err)
|
||||
goto device_create_bail;
|
||||
|
||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
me->channel[i].dev = secure_dev;
|
||||
if (i == CDSP_DOMAIN_ID)
|
||||
me->channel[i].dev = dev;
|
||||
me->channel[i].dev = dev;
|
||||
me->channel[i].ssrcount = 0;
|
||||
me->channel[i].prevssrcount = 0;
|
||||
me->channel[i].issubsystemup = 1;
|
||||
|
@ -3331,11 +3230,7 @@ device_create_bail:
|
|||
&me->channel[i].nb);
|
||||
}
|
||||
if (!IS_ERR_OR_NULL(dev))
|
||||
device_destroy(me->class, MKDEV(MAJOR(me->dev_no),
|
||||
MINOR_NUM_DEV));
|
||||
if (!IS_ERR_OR_NULL(secure_dev))
|
||||
device_destroy(me->class, MKDEV(MAJOR(me->dev_no),
|
||||
MINOR_NUM_SECURE_DEV));
|
||||
device_destroy(me->class, MKDEV(MAJOR(me->dev_no), 0));
|
||||
class_destroy(me->class);
|
||||
class_create_bail:
|
||||
cdev_del(&me->cdev);
|
||||
|
@ -3357,15 +3252,10 @@ static void __exit fastrpc_device_exit(void)
|
|||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
if (!gcinfo[i].name)
|
||||
continue;
|
||||
device_destroy(me->class, MKDEV(MAJOR(me->dev_no), i));
|
||||
subsys_notif_unregister_notifier(me->channel[i].handle,
|
||||
&me->channel[i].nb);
|
||||
}
|
||||
|
||||
/* Destroy the secure and non secure devices */
|
||||
device_destroy(me->class, MKDEV(MAJOR(me->dev_no), MINOR_NUM_DEV));
|
||||
device_destroy(me->class, MKDEV(MAJOR(me->dev_no),
|
||||
MINOR_NUM_SECURE_DEV));
|
||||
|
||||
class_destroy(me->class);
|
||||
cdev_del(&me->cdev);
|
||||
unregister_chrdev_region(me->dev_no, NUM_CHANNELS);
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp"
|
||||
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
|
||||
#define DEVICE_NAME "adsprpc-smd"
|
||||
#define DEVICE_NAME_SECURE "adsprpc-smd-secure"
|
||||
|
||||
/* Set for buffers that have no virtual mapping in userspace */
|
||||
#define FASTRPC_ATTR_NOVA 0x1
|
||||
|
|
|
@ -1752,15 +1752,18 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param)
|
|||
|
||||
i = upd - UPD_WLAN;
|
||||
|
||||
mutex_lock(&driver->md_session_lock);
|
||||
if (driver->md_session_map[peripheral] &&
|
||||
(MD_PERIPHERAL_MASK(peripheral) &
|
||||
diag_mux->mux_mask) &&
|
||||
!driver->pd_session_clear[i]) {
|
||||
DIAG_LOG(DIAG_DEBUG_USERSPACE,
|
||||
"diag_fr: User PD is already logging onto active peripheral logging\n");
|
||||
mutex_unlock(&driver->md_session_lock);
|
||||
driver->pd_session_clear[i] = 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_unlock(&driver->md_session_lock);
|
||||
peripheral_mask =
|
||||
diag_translate_mask(param->pd_mask);
|
||||
param->peripheral_mask = peripheral_mask;
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
#ifdef CONFIG_USB_QCOM_DIAG_BRIDGE
|
||||
#include "diagfwd_hsic.h"
|
||||
#endif
|
||||
#ifdef CONFIG_MSM_MHI
|
||||
#include "diagfwd_mhi.h"
|
||||
#endif
|
||||
#include "diag_dci.h"
|
||||
|
||||
#ifndef CONFIG_USB_QCOM_DIAG_BRIDGE
|
||||
|
|
|
@ -47,8 +47,8 @@ static int virtrc_front_get_clk_id(struct reset_controller_dev *rcdev,
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
ret = habmm_socket_recv(handle, &rsp, &rsp_size,
|
||||
UINT_MAX, 0);
|
||||
ret = habmm_socket_recv(handle, &rsp, &rsp_size, UINT_MAX,
|
||||
HABMM_SOCKET_RECV_FLAGS_UNINTERRUPTIBLE);
|
||||
if (ret) {
|
||||
pr_err("%s: habmm socket receive failed (%d)\n", map->clk_name,
|
||||
ret);
|
||||
|
@ -109,7 +109,8 @@ static int __virtrc_front_reset(struct reset_controller_dev *rcdev,
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
ret = habmm_socket_recv(handle, &rsp, &rsp_size, UINT_MAX, 0);
|
||||
ret = habmm_socket_recv(handle, &rsp, &rsp_size, UINT_MAX,
|
||||
HABMM_SOCKET_RECV_FLAGS_UNINTERRUPTIBLE);
|
||||
if (ret) {
|
||||
pr_err("%s: habmm socket receive failed (%d)\n", map->clk_name,
|
||||
ret);
|
||||
|
|
|
@ -660,7 +660,7 @@ static struct dma_chan *k3_of_dma_simple_xlate(struct of_phandle_args *dma_spec,
|
|||
struct k3_dma_dev *d = ofdma->of_dma_data;
|
||||
unsigned int request = dma_spec->args[0];
|
||||
|
||||
if (request > d->dma_requests)
|
||||
if (request >= d->dma_requests)
|
||||
return NULL;
|
||||
|
||||
return dma_get_slave_channel(&(d->chans[request].vc.chan));
|
||||
|
|
|
@ -160,6 +160,7 @@ enum {
|
|||
CFG_ALPHAM_GRA = 0x1 << 16,
|
||||
CFG_ALPHAM_CFG = 0x2 << 16,
|
||||
CFG_ALPHA_MASK = 0xff << 8,
|
||||
#define CFG_ALPHA(x) ((x) << 8)
|
||||
CFG_PIXCMD_MASK = 0xff,
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ struct armada_ovl_plane_properties {
|
|||
uint16_t contrast;
|
||||
uint16_t saturation;
|
||||
uint32_t colorkey_mode;
|
||||
uint32_t colorkey_enable;
|
||||
};
|
||||
|
||||
struct armada_ovl_plane {
|
||||
|
@ -62,11 +63,13 @@ armada_ovl_update_attr(struct armada_ovl_plane_properties *prop,
|
|||
writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE);
|
||||
|
||||
spin_lock_irq(&dcrtc->irq_lock);
|
||||
armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA,
|
||||
CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
|
||||
dcrtc->base + LCD_SPU_DMA_CTRL1);
|
||||
|
||||
armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG);
|
||||
armada_updatel(prop->colorkey_mode,
|
||||
CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK,
|
||||
dcrtc->base + LCD_SPU_DMA_CTRL1);
|
||||
if (dcrtc->variant->has_spu_adv_reg)
|
||||
armada_updatel(prop->colorkey_enable,
|
||||
ADV_GRACOLORKEY | ADV_VIDCOLORKEY,
|
||||
dcrtc->base + LCD_SPU_ADV_REG);
|
||||
spin_unlock_irq(&dcrtc->irq_lock);
|
||||
}
|
||||
|
||||
|
@ -339,8 +342,17 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane,
|
|||
dplane->prop.colorkey_vb |= K2B(val);
|
||||
update_attr = true;
|
||||
} else if (property == priv->colorkey_mode_prop) {
|
||||
dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK;
|
||||
dplane->prop.colorkey_mode |= CFG_CKMODE(val);
|
||||
if (val == CKMODE_DISABLE) {
|
||||
dplane->prop.colorkey_mode =
|
||||
CFG_CKMODE(CKMODE_DISABLE) |
|
||||
CFG_ALPHAM_CFG | CFG_ALPHA(255);
|
||||
dplane->prop.colorkey_enable = 0;
|
||||
} else {
|
||||
dplane->prop.colorkey_mode =
|
||||
CFG_CKMODE(val) |
|
||||
CFG_ALPHAM_GRA | CFG_ALPHA(0);
|
||||
dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
|
||||
}
|
||||
update_attr = true;
|
||||
} else if (property == priv->brightness_prop) {
|
||||
dplane->prop.brightness = val - 256;
|
||||
|
@ -469,7 +481,9 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
|
|||
dplane->prop.colorkey_yr = 0xfefefe00;
|
||||
dplane->prop.colorkey_ug = 0x01010100;
|
||||
dplane->prop.colorkey_vb = 0x01010100;
|
||||
dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB);
|
||||
dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) |
|
||||
CFG_ALPHAM_GRA | CFG_ALPHA(0);
|
||||
dplane->prop.colorkey_enable = ADV_GRACOLORKEY;
|
||||
dplane->prop.brightness = 0;
|
||||
dplane->prop.contrast = 0x4000;
|
||||
dplane->prop.saturation = 0x4000;
|
||||
|
|
|
@ -312,6 +312,9 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
|
|||
case DRM_CAP_ADDFB2_MODIFIERS:
|
||||
req->value = dev->mode_config.allow_fb_modifiers;
|
||||
break;
|
||||
case DRM_CAP_CRTC_IN_VBLANK_EVENT:
|
||||
req->value = 1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -1098,6 +1098,7 @@ EXPORT_SYMBOL(drm_arm_vblank_event);
|
|||
void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
|
||||
struct drm_pending_vblank_event *e)
|
||||
{
|
||||
e->event.crtc_id = crtc->base.id;
|
||||
drm_arm_vblank_event(crtc->dev, drm_crtc_index(crtc), e);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
|
||||
|
@ -1144,6 +1145,7 @@ EXPORT_SYMBOL(drm_send_vblank_event);
|
|||
void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
|
||||
struct drm_pending_vblank_event *e)
|
||||
{
|
||||
e->event.crtc_id = crtc->base.id;
|
||||
drm_send_vblank_event(crtc->dev, drm_crtc_index(crtc), e);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_send_vblank_event);
|
||||
|
|
|
@ -190,7 +190,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
|
|||
unsigned long val;
|
||||
|
||||
val = readl(ctx->addr + DECON_WINCONx(win));
|
||||
val &= ~WINCONx_BPPMODE_MASK;
|
||||
val &= WINCONx_ENWIN_F;
|
||||
|
||||
switch (fb->pixel_format) {
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
|
@ -278,8 +278,8 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
|
|||
COORDINATE_Y(plane->crtc_y + plane->crtc_h - 1);
|
||||
writel(val, ctx->addr + DECON_VIDOSDxB(win));
|
||||
|
||||
val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
|
||||
VIDOSD_Wx_ALPHA_B_F(0x0);
|
||||
val = VIDOSD_Wx_ALPHA_R_F(0xff) | VIDOSD_Wx_ALPHA_G_F(0xff) |
|
||||
VIDOSD_Wx_ALPHA_B_F(0xff);
|
||||
writel(val, ctx->addr + DECON_VIDOSDxC(win));
|
||||
|
||||
val = VIDOSD_Wx_ALPHA_R_F(0x0) | VIDOSD_Wx_ALPHA_G_F(0x0) |
|
||||
|
|
|
@ -526,21 +526,25 @@ static int gsc_src_set_fmt(struct device *dev, u32 fmt)
|
|||
GSC_IN_CHROMA_ORDER_CRCB);
|
||||
break;
|
||||
case DRM_FORMAT_NV21:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_2P);
|
||||
break;
|
||||
case DRM_FORMAT_NV61:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CRCB |
|
||||
GSC_IN_YUV420_2P);
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV422_2P);
|
||||
break;
|
||||
case DRM_FORMAT_YUV422:
|
||||
cfg |= GSC_IN_YUV422_3P;
|
||||
break;
|
||||
case DRM_FORMAT_YUV420:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_3P);
|
||||
break;
|
||||
case DRM_FORMAT_YVU420:
|
||||
cfg |= GSC_IN_YUV420_3P;
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_3P);
|
||||
break;
|
||||
case DRM_FORMAT_NV12:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_2P);
|
||||
break;
|
||||
case DRM_FORMAT_NV16:
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CBCR |
|
||||
GSC_IN_YUV420_2P);
|
||||
cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV422_2P);
|
||||
break;
|
||||
default:
|
||||
dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt);
|
||||
|
@ -800,18 +804,25 @@ static int gsc_dst_set_fmt(struct device *dev, u32 fmt)
|
|||
GSC_OUT_CHROMA_ORDER_CRCB);
|
||||
break;
|
||||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV61:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_2P);
|
||||
break;
|
||||
case DRM_FORMAT_NV61:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV422_2P);
|
||||
break;
|
||||
case DRM_FORMAT_YUV422:
|
||||
cfg |= GSC_OUT_YUV422_3P;
|
||||
break;
|
||||
case DRM_FORMAT_YUV420:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_3P);
|
||||
break;
|
||||
case DRM_FORMAT_YVU420:
|
||||
cfg |= GSC_OUT_YUV420_3P;
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_3P);
|
||||
break;
|
||||
case DRM_FORMAT_NV12:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_2P);
|
||||
break;
|
||||
case DRM_FORMAT_NV16:
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CBCR |
|
||||
GSC_OUT_YUV420_2P);
|
||||
cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV422_2P);
|
||||
break;
|
||||
default:
|
||||
dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt);
|
||||
|
|
|
@ -138,6 +138,7 @@
|
|||
#define GSC_OUT_YUV420_3P (3 << 4)
|
||||
#define GSC_OUT_YUV422_1P (4 << 4)
|
||||
#define GSC_OUT_YUV422_2P (5 << 4)
|
||||
#define GSC_OUT_YUV422_3P (6 << 4)
|
||||
#define GSC_OUT_YUV444 (7 << 4)
|
||||
#define GSC_OUT_TILE_TYPE_MASK (1 << 2)
|
||||
#define GSC_OUT_TILE_C_16x8 (0 << 2)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright (C) 2013 Red Hat
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
*
|
||||
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
|
@ -48,6 +48,10 @@ enum msm_mdp_display_id {
|
|||
DISPLAY_ID_SECONDARY,
|
||||
DISPLAY_ID_TERTIARY,
|
||||
DISPLAY_ID_QUATERNARY,
|
||||
DISPLAY_ID_QUINARY,
|
||||
DISPLAY_ID_SENARY,
|
||||
DISPLAY_ID_SEPTENARY,
|
||||
DISPLAY_ID_OCTONARY,
|
||||
DISPLAY_ID_MAX
|
||||
};
|
||||
|
||||
|
@ -71,6 +75,14 @@ static inline enum msm_mdp_display_id msm_get_display_id(
|
|||
return DISPLAY_ID_TERTIARY;
|
||||
else if (!strcmp(display_type, "quaternary"))
|
||||
return DISPLAY_ID_QUATERNARY;
|
||||
else if (!strcmp(display_type, "quinary"))
|
||||
return DISPLAY_ID_QUINARY;
|
||||
else if (!strcmp(display_type, "senary"))
|
||||
return DISPLAY_ID_SENARY;
|
||||
else if (!strcmp(display_type, "septenary"))
|
||||
return DISPLAY_ID_SEPTENARY;
|
||||
else if (!strcmp(display_type, "octonary"))
|
||||
return DISPLAY_ID_OCTONARY;
|
||||
else
|
||||
return DISPLAY_ID_NONE;
|
||||
};
|
||||
|
|
|
@ -3045,6 +3045,8 @@ static int _sde_hdmi_parse_dt_modes(struct device_node *np,
|
|||
flags |= DRM_MODE_FLAG_PVSYNC;
|
||||
else
|
||||
flags |= DRM_MODE_FLAG_NVSYNC;
|
||||
|
||||
flags |= DRM_MODE_FLAG_SUPPORTS_RGB;
|
||||
mode->flags = flags;
|
||||
|
||||
if (!rc) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "sde_rm.h"
|
||||
#include "dsi_display.h"
|
||||
#include "sde_hdmi.h"
|
||||
#include "sde_crtc.h"
|
||||
|
||||
#define MDP_SSPP_TOP0_OFF 0x1000
|
||||
#define DISP_INTF_SEL 0x004
|
||||
|
@ -878,12 +879,61 @@ int sde_splash_free_resource(struct msm_kms *kms,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Below function will detach all the pipes of the mixer
|
||||
*/
|
||||
static int _sde_splash_clear_mixer_blendstage(struct msm_kms *kms,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct sde_crtc *sde_crtc;
|
||||
struct sde_crtc_mixer *mixer;
|
||||
int i;
|
||||
struct sde_splash_info *sinfo;
|
||||
struct sde_kms *sde_kms = to_sde_kms(kms);
|
||||
|
||||
sinfo = &sde_kms->splash_info;
|
||||
|
||||
if (!sinfo) {
|
||||
SDE_ERROR("%s(%d): invalid splash info\n", __func__, __LINE__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < state->dev->mode_config.num_crtc; i++) {
|
||||
crtc = state->crtcs[i];
|
||||
if (!crtc) {
|
||||
SDE_ERROR("CRTC is NULL");
|
||||
continue;
|
||||
}
|
||||
sde_crtc = to_sde_crtc(crtc);
|
||||
if (!sde_crtc) {
|
||||
SDE_ERROR("SDE CRTC is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
mixer = sde_crtc->mixers;
|
||||
if (!mixer) {
|
||||
SDE_ERROR("Mixer is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < sde_crtc->num_mixers; i++) {
|
||||
if (mixer[i].hw_ctl->ops.clear_all_blendstages)
|
||||
mixer[i].hw_ctl->ops.clear_all_blendstages(
|
||||
mixer[i].hw_ctl,
|
||||
sinfo->handoff,
|
||||
sinfo->reserved_pipe_info,
|
||||
MAX_BLOCKS);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Below function will notify LK to stop display splash.
|
||||
*/
|
||||
int sde_splash_lk_stop_splash(struct msm_kms *kms,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
int error = 0;
|
||||
struct sde_splash_info *sinfo;
|
||||
struct sde_kms *sde_kms = to_sde_kms(kms);
|
||||
|
||||
|
@ -902,8 +952,10 @@ int sde_splash_lk_stop_splash(struct msm_kms *kms,
|
|||
_sde_splash_notify_lk_stop_splash(sde_kms->hw_intr);
|
||||
|
||||
sinfo->display_splash_enabled = false;
|
||||
|
||||
error = _sde_splash_clear_mixer_blendstage(kms, state);
|
||||
}
|
||||
mutex_unlock(&sde_splash_lock);
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -602,7 +602,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
|
|||
struct nouveau_bo *nvbo;
|
||||
uint32_t data;
|
||||
|
||||
if (unlikely(r->bo_index > req->nr_buffers)) {
|
||||
if (unlikely(r->bo_index >= req->nr_buffers)) {
|
||||
NV_PRINTK(err, cli, "reloc bo index invalid\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
@ -612,7 +612,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
|
|||
if (b->presumed.valid)
|
||||
continue;
|
||||
|
||||
if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
|
||||
if (unlikely(r->reloc_bo_index >= req->nr_buffers)) {
|
||||
NV_PRINTK(err, cli, "reloc container bo index invalid\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
|
|
@ -2266,7 +2266,7 @@ static int a5xx_microcode_load(struct adreno_device *adreno_dev)
|
|||
desc.args[1] = 13;
|
||||
desc.arginfo = SCM_ARGS(2);
|
||||
|
||||
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_BOOT, 0xA), &desc);
|
||||
ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT, 0xA), &desc);
|
||||
if (ret) {
|
||||
pr_err("SCM resume call failed with error %d\n", ret);
|
||||
return ret;
|
||||
|
|
|
@ -2487,8 +2487,14 @@ void wacom_setup_device_quirks(struct wacom *wacom)
|
|||
if (features->type >= INTUOSHT && features->type <= BAMBOO_PT)
|
||||
features->device_type |= WACOM_DEVICETYPE_PAD;
|
||||
|
||||
features->x_max = 4096;
|
||||
features->y_max = 4096;
|
||||
if (features->type == INTUOSHT2) {
|
||||
features->x_max = features->x_max / 10;
|
||||
features->y_max = features->y_max / 10;
|
||||
}
|
||||
else {
|
||||
features->x_max = 4096;
|
||||
features->y_max = 4096;
|
||||
}
|
||||
}
|
||||
else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) {
|
||||
features->device_type |= WACOM_DEVICETYPE_PAD;
|
||||
|
|
|
@ -677,9 +677,6 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
|
|||
struct imx_i2c_dma *dma = i2c_imx->dma;
|
||||
struct device *dev = &i2c_imx->adapter.dev;
|
||||
|
||||
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
|
||||
temp |= I2CR_DMAEN;
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
|
||||
dma->chan_using = dma->chan_rx;
|
||||
dma->dma_transfer_dir = DMA_DEV_TO_MEM;
|
||||
|
@ -792,6 +789,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
|
|||
int i, result;
|
||||
unsigned int temp;
|
||||
int block_data = msgs->flags & I2C_M_RECV_LEN;
|
||||
int use_dma = i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data;
|
||||
|
||||
dev_dbg(&i2c_imx->adapter.dev,
|
||||
"<%s> write slave address: addr=0x%x\n",
|
||||
|
@ -818,12 +816,14 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
|
|||
*/
|
||||
if ((msgs->len - 1) || block_data)
|
||||
temp &= ~I2CR_TXAK;
|
||||
if (use_dma)
|
||||
temp |= I2CR_DMAEN;
|
||||
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
|
||||
imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
|
||||
|
||||
dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
|
||||
|
||||
if (i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data)
|
||||
if (use_dma)
|
||||
return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg);
|
||||
|
||||
/* read data */
|
||||
|
|
|
@ -587,7 +587,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
|
|||
|
||||
/* unmap the data buffer */
|
||||
if (dma_size != 0)
|
||||
dma_unmap_single(&adap->dev, dma_addr, dma_size, dma_direction);
|
||||
dma_unmap_single(dev, dma_addr, dma_size, dma_direction);
|
||||
|
||||
if (unlikely(!time_left)) {
|
||||
dev_err(dev, "completion wait timed out\n");
|
||||
|
|
|
@ -1655,13 +1655,7 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
|
|||
} else
|
||||
return -EINVAL;
|
||||
case IIOCDBGVAR:
|
||||
if (arg) {
|
||||
if (copy_to_user(argp, &dev, sizeof(ulong)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
break;
|
||||
return -EINVAL;
|
||||
default:
|
||||
if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
|
||||
cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
|
||||
|
|
|
@ -3691,6 +3691,13 @@ static int run(struct mddev *mddev)
|
|||
disk->rdev->saved_raid_disk < 0)
|
||||
conf->fullsync = 1;
|
||||
}
|
||||
|
||||
if (disk->replacement &&
|
||||
!test_bit(In_sync, &disk->replacement->flags) &&
|
||||
disk->replacement->saved_raid_disk < 0) {
|
||||
conf->fullsync = 1;
|
||||
}
|
||||
|
||||
disk->recovery_disabled = mddev->recovery_disabled - 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -190,23 +190,25 @@ const uint8_t adv7481_default_edid_data[] = {
|
|||
0x19,
|
||||
/* EDID Structure Version and Revision */
|
||||
0x01, 0x03,
|
||||
/* Display Parameters */
|
||||
/* Display Parameters [20-24] bytes */
|
||||
0x80, 0x10, 0x09, 0x78, 0x0A,
|
||||
/* Color characteristics */
|
||||
/* Color characteristics [25-34] bytes */
|
||||
0x0D, 0xC9, 0xA0, 0x57, 0x47, 0x98, 0x27, 0x12,
|
||||
0x48, 0x4C,
|
||||
/* Established Timings */
|
||||
/* Established Timings [35-36] bytes*/
|
||||
0x21, 0x08, 0x00,
|
||||
/* Standard Timings */
|
||||
/* D1 -> (act_pix(1920)/8)-31 */
|
||||
/* C0 -> (refresh rate - 60) */
|
||||
0xD1, 0xC0, 0xD1, 0x40, 0x81, 0xC0, 0x81, 0x40,
|
||||
0x3B, 0xC0, 0x3B, 0x40, 0x31, 0xC0, 0x31, 0x40,
|
||||
/* Detailed Timings Block */
|
||||
0x1A, 0x36, 0x80, 0xA0, 0x70, 0x38, 0x1F, 0x40,
|
||||
0x30, 0x20, 0x35, 0x00, 0x40, 0x44, 0x21, 0x00,
|
||||
/* Detailed Timings Block | Preferred Timing Mode */
|
||||
0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40,
|
||||
0x58, 0x2C, 0x45, 0x00, 0xDC, 0x0C, 0x11, 0x00,
|
||||
0x00, 0x1E,
|
||||
/* Monitor Descriptor Block 2 */
|
||||
0x00, 0x19, 0x00, 0xA0, 0x50, 0xD0, 0x15, 0x20,
|
||||
0x30, 0x20, 0x35, 0x00, 0x80, 0xD8, 0x10, 0x00,
|
||||
0x01, 0x1D, 0x00, 0xBC, 0x52, 0xD0, 0x1E, 0x20,
|
||||
0xB8, 0x28, 0x55, 0x40, 0xA0, 0x5A, 0x00, 0x00,
|
||||
0x00, 0x1E,
|
||||
/* Monitor Descriptor Block 3 */
|
||||
0x00, 0x00, 0x00, 0xFD, 0x00, 0x17, 0x4B, 0x0F,
|
||||
|
@ -219,16 +221,26 @@ const uint8_t adv7481_default_edid_data[] = {
|
|||
/* Extension Flag CEA */
|
||||
0x01,
|
||||
/* Checksum */
|
||||
0x16,
|
||||
0x5D,
|
||||
|
||||
/* Block 1 (Extension Block) */
|
||||
/* Extension Header */
|
||||
0x02, 0x03, 0x22,
|
||||
/* CEA-861 extension block */
|
||||
/* Block 1 (Extension Block) 128 bytes*/
|
||||
/* Extension Header
|
||||
* 0x23H[35D] - Detailed Timing Descriptor starts
|
||||
*/
|
||||
0x02, 0x03, 0x23,
|
||||
/* Display supports */
|
||||
0x71,
|
||||
/* Video Data Block */
|
||||
0x4C, 0x84, 0x13, 0x3C, 0x03, 0x02, 0x11, 0x12,
|
||||
0x01, 0x90, 0x1F, 0x20, 0x22,
|
||||
/* Data collection block begin
|
||||
* bit 7..5 : Block Type Tag(1:Audio, 2:Video, 3:Vendor specific, 4:speaker)
|
||||
* bit 4..0 : Total number of bytes in block
|
||||
* Eg: Video Data Block
|
||||
* 4D -> D stands for 13 more bytes to read
|
||||
* 90[10010000] -> bit 7:1 stands for native display
|
||||
* -> bit 6..0: VIC value of supported standard resolution
|
||||
*/
|
||||
0x4D, 0x90, 0x1F, 0x22, 0x20, 0x04, 0x13, 0x3E,
|
||||
0x3C, 0x12, 0x11, 0x03, 0x02, 0x01,
|
||||
/* HDMI VSDB */
|
||||
/* Deep color All, Max_TMDS_Clock = 150 MHz */
|
||||
0x68, 0x03, 0x0C, 0x00, 0x10, 0x00, 0x80,
|
||||
|
@ -240,17 +252,17 @@ const uint8_t adv7481_default_edid_data[] = {
|
|||
/* Speaker Allocation Data Block */
|
||||
0x83, 0x01, 0x00, 0x00,
|
||||
/* Detailed Timing Descriptor */
|
||||
0x1A, 0x36, 0x80, 0xA0, 0x70, 0x38, 0x1F, 0x40,
|
||||
0x30, 0x20, 0x35, 0x00, 0x40, 0x44, 0x21, 0x00,
|
||||
0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40,
|
||||
0x58, 0x2C, 0x45, 0x00, 0xDC, 0x0C, 0x11, 0x00,
|
||||
0x00, 0x1E,
|
||||
/* Detailed Timing Descriptor */
|
||||
0x00, 0x19, 0x00, 0xA0, 0x50, 0xD0, 0x15, 0x20,
|
||||
0x30, 0x20, 0x35, 0x00, 0x80, 0xD8, 0x10, 0x00,
|
||||
0x01, 0x1D, 0x00, 0xBC, 0x52, 0xD0, 0x1E, 0x20,
|
||||
0xB8, 0x28, 0x55, 0x40, 0xA0, 0x5A, 0x00, 0x00,
|
||||
0x00, 0x1E,
|
||||
/* Detailed Timing Descriptor */
|
||||
0x41, 0x0A, 0xD0, 0xA0, 0x20, 0xE0, 0x13, 0x10,
|
||||
0x30, 0x20, 0x3A, 0x00, 0xD8, 0x90, 0x00, 0x00,
|
||||
0x00, 0x18,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
/* Detailed Timing Descriptor */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -260,9 +272,9 @@ const uint8_t adv7481_default_edid_data[] = {
|
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
/* DTD padding */
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
/* Checksum */
|
||||
0x8C
|
||||
0xFB
|
||||
};
|
||||
|
||||
#define ADV7481_EDID_SIZE ARRAY_SIZE(adv7481_default_edid_data)
|
||||
|
|
|
@ -836,9 +836,11 @@ static irqreturn_t msm_cpp_irq(int irq_num, void *data)
|
|||
if (irq_status & 0x8) {
|
||||
tx_level = msm_camera_io_r(cpp_dev->base +
|
||||
MSM_CPP_MICRO_FIFO_TX_STAT) >> 2;
|
||||
for (i = 0; i < tx_level; i++) {
|
||||
tx_fifo[i] = msm_camera_io_r(cpp_dev->base +
|
||||
MSM_CPP_MICRO_FIFO_TX_DATA);
|
||||
if (tx_level < MSM_CPP_TX_FIFO_LEVEL) {
|
||||
for (i = 0; i < tx_level; i++) {
|
||||
tx_fifo[i] = msm_camera_io_r(cpp_dev->base +
|
||||
MSM_CPP_MICRO_FIFO_TX_DATA);
|
||||
}
|
||||
} else {
|
||||
pr_err("Fatal invalid tx level %d", tx_level);
|
||||
goto err;
|
||||
|
|
|
@ -1634,6 +1634,7 @@ struct bnx2x {
|
|||
struct link_vars link_vars;
|
||||
u32 link_cnt;
|
||||
struct bnx2x_link_report_data last_reported_link;
|
||||
bool force_link_down;
|
||||
|
||||
struct mdio_if_info mdio;
|
||||
|
||||
|
|
|
@ -1277,6 +1277,11 @@ void __bnx2x_link_report(struct bnx2x *bp)
|
|||
{
|
||||
struct bnx2x_link_report_data cur_data;
|
||||
|
||||
if (bp->force_link_down) {
|
||||
bp->link_vars.link_up = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* reread mf_cfg */
|
||||
if (IS_PF(bp) && !CHIP_IS_E1(bp))
|
||||
bnx2x_read_mf_cfg(bp);
|
||||
|
@ -2840,6 +2845,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
|
|||
bp->pending_max = 0;
|
||||
}
|
||||
|
||||
bp->force_link_down = false;
|
||||
if (bp->port.pmf) {
|
||||
rc = bnx2x_initial_phy_init(bp, load_mode);
|
||||
if (rc)
|
||||
|
|
|
@ -10222,6 +10222,12 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work)
|
|||
bp->sp_rtnl_state = 0;
|
||||
smp_mb();
|
||||
|
||||
/* Immediately indicate link as down */
|
||||
bp->link_vars.link_up = 0;
|
||||
bp->force_link_down = true;
|
||||
netif_carrier_off(bp->dev);
|
||||
BNX2X_ERR("Indicating link is down due to Tx-timeout\n");
|
||||
|
||||
bnx2x_nic_unload(bp, UNLOAD_NORMAL, true);
|
||||
bnx2x_nic_load(bp, LOAD_NORMAL);
|
||||
|
||||
|
|
|
@ -4591,7 +4591,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
|
|||
rc = bnxt_request_irq(bp);
|
||||
if (rc) {
|
||||
netdev_err(bp->dev, "bnxt_request_irq err: %x\n", rc);
|
||||
goto open_err;
|
||||
goto open_err_irq;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4629,6 +4629,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
|
|||
|
||||
open_err:
|
||||
bnxt_disable_napi(bp);
|
||||
|
||||
open_err_irq:
|
||||
bnxt_del_napi(bp);
|
||||
|
||||
open_err_free_mem:
|
||||
|
|
|
@ -338,7 +338,7 @@ static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable)
|
|||
"Can't %s DCB Priority on port %d, TX Queue %d: err=%d\n",
|
||||
enable ? "set" : "unset", pi->port_id, i, -err);
|
||||
else
|
||||
txq->dcb_prio = value;
|
||||
txq->dcb_prio = enable ? value : 0;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_CHELSIO_T4_DCB */
|
||||
|
|
|
@ -78,7 +78,6 @@ void enic_rfs_flw_tbl_init(struct enic *enic)
|
|||
enic->rfs_h.max = enic->config.num_arfs;
|
||||
enic->rfs_h.free = enic->rfs_h.max;
|
||||
enic->rfs_h.toclean = 0;
|
||||
enic_rfs_timer_start(enic);
|
||||
}
|
||||
|
||||
void enic_rfs_flw_tbl_free(struct enic *enic)
|
||||
|
@ -87,7 +86,6 @@ void enic_rfs_flw_tbl_free(struct enic *enic)
|
|||
|
||||
enic_rfs_timer_stop(enic);
|
||||
spin_lock_bh(&enic->rfs_h.lock);
|
||||
enic->rfs_h.free = 0;
|
||||
for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
|
||||
struct hlist_head *hhead;
|
||||
struct hlist_node *tmp;
|
||||
|
@ -98,6 +96,7 @@ void enic_rfs_flw_tbl_free(struct enic *enic)
|
|||
enic_delfltr(enic, n->fltr_id);
|
||||
hlist_del(&n->node);
|
||||
kfree(n);
|
||||
enic->rfs_h.free++;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&enic->rfs_h.lock);
|
||||
|
|
|
@ -1760,7 +1760,7 @@ static int enic_open(struct net_device *netdev)
|
|||
vnic_intr_unmask(&enic->intr[i]);
|
||||
|
||||
enic_notify_timer_start(enic);
|
||||
enic_rfs_flw_tbl_init(enic);
|
||||
enic_rfs_timer_start(enic);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -2694,6 +2694,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
enic->notify_timer.function = enic_notify_timer;
|
||||
enic->notify_timer.data = (unsigned long)enic;
|
||||
|
||||
enic_rfs_flw_tbl_init(enic);
|
||||
enic_set_rx_coal_setting(enic);
|
||||
INIT_WORK(&enic->reset, enic_reset);
|
||||
INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset);
|
||||
|
|
|
@ -100,9 +100,9 @@ static void unfill_desc(struct hnae_ring *ring)
|
|||
ring_ptr_move_bw(ring, next_to_use);
|
||||
}
|
||||
|
||||
int hns_nic_net_xmit_hw(struct net_device *ndev,
|
||||
struct sk_buff *skb,
|
||||
struct hns_nic_ring_data *ring_data)
|
||||
netdev_tx_t hns_nic_net_xmit_hw(struct net_device *ndev,
|
||||
struct sk_buff *skb,
|
||||
struct hns_nic_ring_data *ring_data)
|
||||
{
|
||||
struct hns_nic_priv *priv = netdev_priv(ndev);
|
||||
struct hnae_ring *ring = ring_data->ring;
|
||||
|
@ -172,6 +172,10 @@ int hns_nic_net_xmit_hw(struct net_device *ndev,
|
|||
dev_queue = netdev_get_tx_queue(ndev, skb->queue_mapping);
|
||||
netdev_tx_sent_queue(dev_queue, skb->len);
|
||||
|
||||
ndev->trans_start = jiffies;
|
||||
ndev->stats.tx_bytes += skb->len;
|
||||
ndev->stats.tx_packets++;
|
||||
|
||||
wmb(); /* commit all data before submit */
|
||||
assert(skb->queue_mapping < priv->ae_handle->q_num);
|
||||
hnae_queue_xmit(priv->ae_handle->qs[skb->queue_mapping], buf_num);
|
||||
|
@ -1089,17 +1093,11 @@ static netdev_tx_t hns_nic_net_xmit(struct sk_buff *skb,
|
|||
struct net_device *ndev)
|
||||
{
|
||||
struct hns_nic_priv *priv = netdev_priv(ndev);
|
||||
int ret;
|
||||
|
||||
assert(skb->queue_mapping < ndev->ae_handle->q_num);
|
||||
ret = hns_nic_net_xmit_hw(ndev, skb,
|
||||
&tx_ring_data(priv, skb->queue_mapping));
|
||||
if (ret == NETDEV_TX_OK) {
|
||||
ndev->trans_start = jiffies;
|
||||
ndev->stats.tx_bytes += skb->len;
|
||||
ndev->stats.tx_packets++;
|
||||
}
|
||||
return (netdev_tx_t)ret;
|
||||
|
||||
return hns_nic_net_xmit_hw(ndev, skb,
|
||||
&tx_ring_data(priv, skb->queue_mapping));
|
||||
}
|
||||
|
||||
static int hns_nic_change_mtu(struct net_device *ndev, int new_mtu)
|
||||
|
|
|
@ -77,8 +77,8 @@ void hns_ethtool_set_ops(struct net_device *ndev);
|
|||
void hns_nic_net_reset(struct net_device *ndev);
|
||||
void hns_nic_net_reinit(struct net_device *netdev);
|
||||
int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h);
|
||||
int hns_nic_net_xmit_hw(struct net_device *ndev,
|
||||
struct sk_buff *skb,
|
||||
struct hns_nic_ring_data *ring_data);
|
||||
netdev_tx_t hns_nic_net_xmit_hw(struct net_device *ndev,
|
||||
struct sk_buff *skb,
|
||||
struct hns_nic_ring_data *ring_data);
|
||||
|
||||
#endif /**__HNS_ENET_H */
|
||||
|
|
|
@ -1814,7 +1814,12 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
|
|||
if (enable_addr != 0)
|
||||
rar_high |= IXGBE_RAH_AV;
|
||||
|
||||
/* Record lower 32 bits of MAC address and then make
|
||||
* sure that write is flushed to hardware before writing
|
||||
* the upper 16 bits and setting the valid bit.
|
||||
*/
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
|
||||
IXGBE_WRITE_FLUSH(hw);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
|
||||
|
||||
return 0;
|
||||
|
@ -1846,8 +1851,13 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
|
|||
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
|
||||
rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
|
||||
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
|
||||
/* Clear the address valid bit and upper 16 bits of the address
|
||||
* before clearing the lower bits. This way we aren't updating
|
||||
* a live filter.
|
||||
*/
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
|
||||
IXGBE_WRITE_FLUSH(hw);
|
||||
IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
|
||||
|
||||
/* clear VMDq pool/queue selection for this RAR */
|
||||
hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
|
||||
|
|
|
@ -461,8 +461,16 @@ static irqreturn_t qed_single_int(int irq, void *dev_instance)
|
|||
/* Fastpath interrupts */
|
||||
for (j = 0; j < 64; j++) {
|
||||
if ((0x2ULL << j) & status) {
|
||||
hwfn->simd_proto_handler[j].func(
|
||||
hwfn->simd_proto_handler[j].token);
|
||||
struct qed_simd_fp_handler *p_handler =
|
||||
&hwfn->simd_proto_handler[j];
|
||||
|
||||
if (p_handler->func)
|
||||
p_handler->func(p_handler->token);
|
||||
else
|
||||
DP_NOTICE(hwfn,
|
||||
"Not calling fastpath handler as it is NULL [handler #%d, status 0x%llx]\n",
|
||||
j, status);
|
||||
|
||||
status &= ~(0x2ULL << j);
|
||||
rc = IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
@ -1128,6 +1128,8 @@ static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp,
|
|||
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
|
||||
|
||||
ret = kstrtoul(buf, 16, &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (data) {
|
||||
case QLC_83XX_FLASH_SECTOR_ERASE_CMD:
|
||||
|
|
|
@ -635,7 +635,7 @@ qcaspi_netdev_open(struct net_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
netif_start_queue(qca->net_dev);
|
||||
/* SPI thread takes care of TX queue */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -739,6 +739,9 @@ qcaspi_netdev_tx_timeout(struct net_device *dev)
|
|||
qca->net_dev->stats.tx_errors++;
|
||||
/* Trigger tx queue flush and QCA7000 reset */
|
||||
qca->sync = QCASPI_SYNC_UNKNOWN;
|
||||
|
||||
if (qca->spi_thread)
|
||||
wake_up_process(qca->spi_thread);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -865,22 +868,22 @@ qca_spi_probe(struct spi_device *spi)
|
|||
|
||||
if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) ||
|
||||
(qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) {
|
||||
dev_info(&spi->dev, "Invalid clkspeed: %d\n",
|
||||
qcaspi_clkspeed);
|
||||
dev_err(&spi->dev, "Invalid clkspeed: %d\n",
|
||||
qcaspi_clkspeed);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((qcaspi_burst_len < QCASPI_BURST_LEN_MIN) ||
|
||||
(qcaspi_burst_len > QCASPI_BURST_LEN_MAX)) {
|
||||
dev_info(&spi->dev, "Invalid burst len: %d\n",
|
||||
qcaspi_burst_len);
|
||||
dev_err(&spi->dev, "Invalid burst len: %d\n",
|
||||
qcaspi_burst_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((qcaspi_pluggable < QCASPI_PLUGGABLE_MIN) ||
|
||||
(qcaspi_pluggable > QCASPI_PLUGGABLE_MAX)) {
|
||||
dev_info(&spi->dev, "Invalid pluggable: %d\n",
|
||||
qcaspi_pluggable);
|
||||
dev_err(&spi->dev, "Invalid pluggable: %d\n",
|
||||
qcaspi_pluggable);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -941,8 +944,8 @@ qca_spi_probe(struct spi_device *spi)
|
|||
}
|
||||
|
||||
if (register_netdev(qcaspi_devs)) {
|
||||
dev_info(&spi->dev, "Unable to register net device %s\n",
|
||||
qcaspi_devs->name);
|
||||
dev_err(&spi->dev, "Unable to register net device %s\n",
|
||||
qcaspi_devs->name);
|
||||
free_netdev(qcaspi_devs);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
|
@ -1517,6 +1517,10 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
|
|||
|
||||
static int match_first_device(struct device *dev, void *data)
|
||||
{
|
||||
if (dev->parent && dev->parent->of_node)
|
||||
return of_device_is_compatible(dev->parent->of_node,
|
||||
"ti,davinci_mdio");
|
||||
|
||||
return !strncmp(dev_name(dev), "davinci_mdio", 12);
|
||||
}
|
||||
|
||||
|
|
|
@ -89,10 +89,6 @@
|
|||
static const char banner[] __initconst = KERN_INFO \
|
||||
"AX.25: bpqether driver version 004\n";
|
||||
|
||||
static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
|
||||
static char bpq_eth_addr[6];
|
||||
|
||||
static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
|
||||
static int bpq_device_event(struct notifier_block *, unsigned long, void *);
|
||||
|
||||
|
@ -515,8 +511,8 @@ static int bpq_new_device(struct net_device *edev)
|
|||
bpq->ethdev = edev;
|
||||
bpq->axdev = ndev;
|
||||
|
||||
memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr));
|
||||
memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr));
|
||||
eth_broadcast_addr(bpq->dest_addr);
|
||||
eth_broadcast_addr(bpq->acpt_addr);
|
||||
|
||||
err = register_netdevice(ndev);
|
||||
if (err)
|
||||
|
|
|
@ -932,7 +932,7 @@ at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
|
|||
static int
|
||||
at86rf230_ed(struct ieee802154_hw *hw, u8 *level)
|
||||
{
|
||||
BUG_ON(!level);
|
||||
WARN_ON(!level);
|
||||
*level = 0xbe;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1108,8 +1108,7 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw,
|
|||
if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
|
||||
u16 addr = le16_to_cpu(filt->short_addr);
|
||||
|
||||
dev_vdbg(&lp->spi->dev,
|
||||
"at86rf230_set_hw_addr_filt called for saddr\n");
|
||||
dev_vdbg(&lp->spi->dev, "%s called for saddr\n", __func__);
|
||||
__at86rf230_write(lp, RG_SHORT_ADDR_0, addr);
|
||||
__at86rf230_write(lp, RG_SHORT_ADDR_1, addr >> 8);
|
||||
}
|
||||
|
@ -1117,8 +1116,7 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw,
|
|||
if (changed & IEEE802154_AFILT_PANID_CHANGED) {
|
||||
u16 pan = le16_to_cpu(filt->pan_id);
|
||||
|
||||
dev_vdbg(&lp->spi->dev,
|
||||
"at86rf230_set_hw_addr_filt called for pan id\n");
|
||||
dev_vdbg(&lp->spi->dev, "%s called for pan id\n", __func__);
|
||||
__at86rf230_write(lp, RG_PAN_ID_0, pan);
|
||||
__at86rf230_write(lp, RG_PAN_ID_1, pan >> 8);
|
||||
}
|
||||
|
@ -1127,15 +1125,13 @@ at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw,
|
|||
u8 i, addr[8];
|
||||
|
||||
memcpy(addr, &filt->ieee_addr, 8);
|
||||
dev_vdbg(&lp->spi->dev,
|
||||
"at86rf230_set_hw_addr_filt called for IEEE addr\n");
|
||||
dev_vdbg(&lp->spi->dev, "%s called for IEEE addr\n", __func__);
|
||||
for (i = 0; i < 8; i++)
|
||||
__at86rf230_write(lp, RG_IEEE_ADDR_0 + i, addr[i]);
|
||||
}
|
||||
|
||||
if (changed & IEEE802154_AFILT_PANC_CHANGED) {
|
||||
dev_vdbg(&lp->spi->dev,
|
||||
"at86rf230_set_hw_addr_filt called for panc change\n");
|
||||
dev_vdbg(&lp->spi->dev, "%s called for panc change\n", __func__);
|
||||
if (filt->pan_coord)
|
||||
at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 1);
|
||||
else
|
||||
|
@ -1239,7 +1235,6 @@ at86rf230_set_cca_mode(struct ieee802154_hw *hw,
|
|||
return at86rf230_write_subreg(lp, SR_CCA_MODE, val);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
at86rf230_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
|
||||
{
|
||||
|
|
|
@ -49,7 +49,7 @@ struct fakelb_phy {
|
|||
|
||||
static int fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)
|
||||
{
|
||||
BUG_ON(!level);
|
||||
WARN_ON(!level);
|
||||
*level = 0xbe;
|
||||
|
||||
return 0;
|
||||
|
|
171
drivers/net/phy/mdio_device.c
Normal file
171
drivers/net/phy/mdio_device.c
Normal file
|
@ -0,0 +1,171 @@
|
|||
/* Framework for MDIO devices, other than PHYs.
|
||||
*
|
||||
* Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mdio.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/unistd.h>
|
||||
|
||||
void mdio_device_free(struct mdio_device *mdiodev)
|
||||
{
|
||||
put_device(&mdiodev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(mdio_device_free);
|
||||
|
||||
static void mdio_device_release(struct device *dev)
|
||||
{
|
||||
kfree(to_mdio_device(dev));
|
||||
}
|
||||
|
||||
struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr)
|
||||
{
|
||||
struct mdio_device *mdiodev;
|
||||
|
||||
/* We allocate the device, and initialize the default values */
|
||||
mdiodev = kzalloc(sizeof(*mdiodev), GFP_KERNEL);
|
||||
if (!mdiodev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mdiodev->dev.release = mdio_device_release;
|
||||
mdiodev->dev.parent = &bus->dev;
|
||||
mdiodev->dev.bus = &mdio_bus_type;
|
||||
mdiodev->device_free = mdio_device_free;
|
||||
mdiodev->device_remove = mdio_device_remove;
|
||||
mdiodev->bus = bus;
|
||||
mdiodev->addr = addr;
|
||||
|
||||
dev_set_name(&mdiodev->dev, PHY_ID_FMT, bus->id, addr);
|
||||
|
||||
device_initialize(&mdiodev->dev);
|
||||
|
||||
return mdiodev;
|
||||
}
|
||||
EXPORT_SYMBOL(mdio_device_create);
|
||||
|
||||
/**
|
||||
* mdio_device_register - Register the mdio device on the MDIO bus
|
||||
* @mdiodev: mdio_device structure to be added to the MDIO bus
|
||||
*/
|
||||
int mdio_device_register(struct mdio_device *mdiodev)
|
||||
{
|
||||
int err;
|
||||
|
||||
dev_info(&mdiodev->dev, "mdio_device_register\n");
|
||||
|
||||
err = mdiobus_register_device(mdiodev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = device_add(&mdiodev->dev);
|
||||
if (err) {
|
||||
pr_err("MDIO %d failed to add\n", mdiodev->addr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
mdiobus_unregister_device(mdiodev);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mdio_device_register);
|
||||
|
||||
/**
|
||||
* mdio_device_remove - Remove a previously registered mdio device from the
|
||||
* MDIO bus
|
||||
* @mdiodev: mdio_device structure to remove
|
||||
*
|
||||
* This doesn't free the mdio_device itself, it merely reverses the effects
|
||||
* of mdio_device_register(). Use mdio_device_free() to free the device
|
||||
* after calling this function.
|
||||
*/
|
||||
void mdio_device_remove(struct mdio_device *mdiodev)
|
||||
{
|
||||
device_del(&mdiodev->dev);
|
||||
mdiobus_unregister_device(mdiodev);
|
||||
}
|
||||
EXPORT_SYMBOL(mdio_device_remove);
|
||||
|
||||
/**
|
||||
* mdio_probe - probe an MDIO device
|
||||
* @dev: device to probe
|
||||
*
|
||||
* Description: Take care of setting up the mdio_device structure
|
||||
* and calling the driver to probe the device.
|
||||
*/
|
||||
static int mdio_probe(struct device *dev)
|
||||
{
|
||||
struct mdio_device *mdiodev = to_mdio_device(dev);
|
||||
struct device_driver *drv = mdiodev->dev.driver;
|
||||
struct mdio_driver *mdiodrv = to_mdio_driver(drv);
|
||||
int err = 0;
|
||||
|
||||
if (mdiodrv->probe)
|
||||
err = mdiodrv->probe(mdiodev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mdio_remove(struct device *dev)
|
||||
{
|
||||
struct mdio_device *mdiodev = to_mdio_device(dev);
|
||||
struct device_driver *drv = mdiodev->dev.driver;
|
||||
struct mdio_driver *mdiodrv = to_mdio_driver(drv);
|
||||
|
||||
if (mdiodrv->remove)
|
||||
mdiodrv->remove(mdiodev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mdio_driver_register - register an mdio_driver with the MDIO layer
|
||||
* @new_driver: new mdio_driver to register
|
||||
*/
|
||||
int mdio_driver_register(struct mdio_driver *drv)
|
||||
{
|
||||
struct mdio_driver_common *mdiodrv = &drv->mdiodrv;
|
||||
int retval;
|
||||
|
||||
pr_info("mdio_driver_register: %s\n", mdiodrv->driver.name);
|
||||
|
||||
mdiodrv->driver.bus = &mdio_bus_type;
|
||||
mdiodrv->driver.probe = mdio_probe;
|
||||
mdiodrv->driver.remove = mdio_remove;
|
||||
|
||||
retval = driver_register(&mdiodrv->driver);
|
||||
if (retval) {
|
||||
pr_err("%s: Error %d in registering driver\n",
|
||||
mdiodrv->driver.name, retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mdio_driver_register);
|
||||
|
||||
void mdio_driver_unregister(struct mdio_driver *drv)
|
||||
{
|
||||
struct mdio_driver_common *mdiodrv = &drv->mdiodrv;
|
||||
|
||||
driver_unregister(&mdiodrv->driver);
|
||||
}
|
||||
EXPORT_SYMBOL(mdio_driver_unregister);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue