diff --git a/Documentation/ABI/testing/procfs-concurrent_time b/Documentation/ABI/testing/procfs-concurrent_time deleted file mode 100644 index 55b414289b40..000000000000 --- a/Documentation/ABI/testing/procfs-concurrent_time +++ /dev/null @@ -1,16 +0,0 @@ -What: /proc/uid_concurrent_active_time -Date: December 2018 -Contact: Connor O'Brien -Description: - The /proc/uid_concurrent_active_time file displays aggregated cputime - numbers for each uid, broken down by the total number of cores that were - active while the uid's task was running. - -What: /proc/uid_concurrent_policy_time -Date: December 2018 -Contact: Connor O'Brien -Description: - The /proc/uid_concurrent_policy_time file displays aggregated cputime - numbers for each uid, broken down based on the cpufreq policy - of the core used by the uid's task and the number of cores associated - with that policy that were active while the uid's task was running. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 1f0f0bc3767e..084c473337c2 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -136,6 +136,10 @@ dynamic table installation which will install SSDT tables to /sys/firmware/acpi/tables/dynamic. + acpi_no_watchdog [HW,ACPI,WDT] + Ignore the ACPI-based watchdog interface (WDAT) and let + a native driver control the watchdog device instead. + acpi_rsdp= [ACPI,EFI,KEXEC] Pass the RSDP address to the kernel, mostly used on machines running EFI runtime service to boot the diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index fbcd185d15da..dc444b8d3704 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -633,6 +633,17 @@ from a passphrase or other low-entropy user credential. FS_IOC_GET_ENCRYPTION_PWSALT is deprecated. Instead, prefer to generate and manage any needed salt(s) in userspace. +Getting a file's encryption nonce +--------------------------------- + +Since Linux v5.7, the ioctl FS_IOC_GET_ENCRYPTION_NONCE is supported. +On encrypted files and directories it gets the inode's 16-byte nonce. +On unencrypted files and directories, it fails with ENODATA. + +This ioctl can be useful for automated tests which verify that the +encryption is being done correctly. It is not needed for normal use +of fscrypt. + Adding keys ----------- diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst index f18506083ced..26c093969573 100644 --- a/Documentation/filesystems/porting.rst +++ b/Documentation/filesystems/porting.rst @@ -850,3 +850,11 @@ business doing so. d_alloc_pseudo() is internal-only; uses outside of alloc_file_pseudo() are very suspect (and won't work in modules). Such uses are very likely to be misspelled d_alloc_anon(). + +--- + +**mandatory** + +[should've been added in 2016] stale comment in finish_open() nonwithstanding, +failure exits in ->atomic_open() instances should *NOT* fput() the file, +no matter what. Everything is handled by the caller. diff --git a/Documentation/kbuild/modules.rst b/Documentation/kbuild/modules.rst index 774a998dcf37..199ce72bf922 100644 --- a/Documentation/kbuild/modules.rst +++ b/Documentation/kbuild/modules.rst @@ -470,9 +470,9 @@ build. The syntax of the Module.symvers file is:: - + - 0xe1cc2a05 usb_stor_suspend USB_STORAGE drivers/usb/storage/usb-storage EXPORT_SYMBOL_GPL + 0xe1cc2a05 usb_stor_suspend drivers/usb/storage/usb-storage EXPORT_SYMBOL_GPL USB_STORAGE The fields are separated by tabs and values may be empty (e.g. if no namespace is defined for an exported symbol). diff --git a/Documentation/usb/index.rst b/Documentation/usb/index.rst index e55386a4abfb..370d1e0193e7 100644 --- a/Documentation/usb/index.rst +++ b/Documentation/usb/index.rst @@ -23,6 +23,7 @@ USB support mtouchusb ohci rio + raw-gadget usbip_protocol usbmon usb-serial diff --git a/Documentation/usb/raw-gadget.rst b/Documentation/usb/raw-gadget.rst new file mode 100644 index 000000000000..9e78cb858f86 --- /dev/null +++ b/Documentation/usb/raw-gadget.rst @@ -0,0 +1,61 @@ +============== +USB Raw Gadget +============== + +USB Raw Gadget is a kernel module that provides a userspace interface for +the USB Gadget subsystem. Essentially it allows to emulate USB devices +from userspace. Enabled with CONFIG_USB_RAW_GADGET. Raw Gadget is +currently a strictly debugging feature and shouldn't be used in +production, use GadgetFS instead. + +Comparison to GadgetFS +~~~~~~~~~~~~~~~~~~~~~~ + +Raw Gadget is similar to GadgetFS, but provides a more low-level and +direct access to the USB Gadget layer for the userspace. The key +differences are: + +1. Every USB request is passed to the userspace to get a response, while + GadgetFS responds to some USB requests internally based on the provided + descriptors. However note, that the UDC driver might respond to some + requests on its own and never forward them to the Gadget layer. + +2. GadgetFS performs some sanity checks on the provided USB descriptors, + while Raw Gadget allows you to provide arbitrary data as responses to + USB requests. + +3. Raw Gadget provides a way to select a UDC device/driver to bind to, + while GadgetFS currently binds to the first available UDC. + +4. Raw Gadget uses predictable endpoint names (handles) across different + UDCs (as long as UDCs have enough endpoints of each required transfer + type). + +5. Raw Gadget has ioctl-based interface instead of a filesystem-based one. + +Userspace interface +~~~~~~~~~~~~~~~~~~~ + +To create a Raw Gadget instance open /dev/raw-gadget. Multiple raw-gadget +instances (bound to different UDCs) can be used at the same time. The +interaction with the opened file happens through the ioctl() calls, see +comments in include/uapi/linux/usb/raw_gadget.h for details. + +The typical usage of Raw Gadget looks like: + +1. Open Raw Gadget instance via /dev/raw-gadget. +2. Initialize the instance via USB_RAW_IOCTL_INIT. +3. Launch the instance with USB_RAW_IOCTL_RUN. +4. In a loop issue USB_RAW_IOCTL_EVENT_FETCH calls to receive events from + Raw Gadget and react to those depending on what kind of USB device + needs to be emulated. + +Potential future improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Implement ioctl's for setting/clearing halt status on endpoints. + +- Reporting more events (suspend, resume, etc.) through + USB_RAW_IOCTL_EVENT_FETCH. + +- Support O_NONBLOCK I/O. diff --git a/Makefile b/Makefile index 8348e298d7b7..e28dbcd9caa4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 4 -SUBLEVEL = 24 +SUBLEVEL = 30 EXTRAVERSION = NAME = Kleptomaniac Octopus @@ -901,7 +901,8 @@ endif ifdef CONFIG_CFI_CLANG CC_FLAGS_CFI := -fsanitize=cfi \ - -fno-sanitize-cfi-canonical-jump-tables + -fno-sanitize-cfi-canonical-jump-tables \ + -fno-sanitize-blacklist ifdef CONFIG_MODULES CC_FLAGS_CFI += -fsanitize-cfi-cross-dso @@ -1135,8 +1136,8 @@ endif autoksyms_h := $(if $(CONFIG_TRIM_UNUSED_KSYMS), include/generated/autoksyms.h) quiet_cmd_autoksyms_h = GEN $@ - cmd_autoksyms_h = mkdir -p $(dir $@); $(CONFIG_SHELL) \ - $(srctree)/scripts/gen_autoksyms.sh $@ + cmd_autoksyms_h = mkdir -p $(dir $@); \ + $(CONFIG_SHELL) $(srctree)/scripts/gen_autoksyms.sh $@ $(autoksyms_h): $(call cmd,autoksyms_h) @@ -1322,7 +1323,7 @@ ifneq ($(dtstree),) %.dtb: include/config/kernel.release scripts_dtc $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ -PHONY += dtbs dtbs_install dt_binding_check +PHONY += dtbs dtbs_install dtbs_check dtbs dtbs_check: include/config/kernel.release scripts_dtc $(Q)$(MAKE) $(build)=$(dtstree) @@ -1342,6 +1343,7 @@ PHONY += scripts_dtc scripts_dtc: scripts_basic $(Q)$(MAKE) $(build)=scripts/dtc +PHONY += dt_binding_check dt_binding_check: scripts_dtc $(Q)$(MAKE) $(build)=Documentation/devicetree/bindings diff --git a/abi_gki_aarch64.xml b/abi_gki_aarch64.xml index bf0572358420..9323df2a9055 100644 --- a/abi_gki_aarch64.xml +++ b/abi_gki_aarch64.xml @@ -2,13 +2,23 @@ + + + + + + + + + + @@ -16,14 +26,22 @@ + + + + + + + + @@ -32,7 +50,12 @@ - + + + + + + @@ -45,37 +68,53 @@ + + + + + + + + + + + + + + + + @@ -83,6 +122,7 @@ + @@ -93,44 +133,73 @@ + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + @@ -138,62 +207,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -201,19 +359,40 @@ + + + + + + + + + + + + + + + + + + + + + @@ -223,16 +402,39 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -244,15 +446,24 @@ + + + + + + + + + @@ -265,13 +476,18 @@ + + + + + @@ -281,13 +497,20 @@ + + + + + + + @@ -295,16 +518,27 @@ + + + + + + + + + + + @@ -312,34 +546,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -347,78 +628,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -427,11 +762,15 @@ + + + + @@ -440,23 +779,36 @@ + + + + + + + + + + + - + + + @@ -464,32 +816,49 @@ + + + + + + + + + + + + + + + + + @@ -499,25 +868,32 @@ + + + + + + + @@ -526,6 +902,7 @@ + @@ -538,17 +915,28 @@ + + + + + + + + + + + @@ -556,11 +944,13 @@ + + @@ -569,6 +959,7 @@ + @@ -579,27 +970,49 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -610,9 +1023,11 @@ + + @@ -643,12 +1058,25 @@ + + + + + + + + + + + + + @@ -665,6 +1093,7 @@ + @@ -673,6 +1102,7 @@ + @@ -685,8 +1115,11 @@ + + + @@ -695,20 +1128,34 @@ + + + + + + + + + + + + + + @@ -717,6 +1164,7 @@ + @@ -732,9 +1180,14 @@ + + + + + @@ -742,8 +1195,10 @@ + + @@ -754,6 +1209,7 @@ + @@ -773,30 +1229,49 @@ + + + + + + + + + + + + + + + + + + + @@ -806,73 +1281,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -880,15 +1411,29 @@ + + + + + + + + + + + + + + @@ -898,10 +1443,12 @@ + + @@ -909,9 +1456,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -919,48 +1515,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -976,51 +1626,101 @@ + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1028,18 +1728,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1048,13 +1777,18 @@ + + + + + @@ -1064,6 +1798,8 @@ + + @@ -1078,16 +1814,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1100,23 +1885,32 @@ + + + + + + + + + @@ -1125,6 +1919,7 @@ + @@ -1132,8 +1927,13 @@ + + + + + @@ -1141,13 +1941,18 @@ + + + + + @@ -1155,25 +1960,40 @@ + + + + + + + + + + + + + + + @@ -1185,10 +2005,16 @@ + + + + + + @@ -1206,79 +2032,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1295,11 +2185,15 @@ + + + + @@ -1307,6 +2201,8 @@ + + @@ -1321,21 +2217,41 @@ + + + + + + + + + + + + + + + + + + + + @@ -1346,13 +2262,14 @@ + + - - + @@ -1360,41 +2277,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1402,54 +2355,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1460,31 +2442,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1494,28 +2500,48 @@ + + + + + + + + + + + + + + + + + + + + @@ -1523,22 +2549,36 @@ + + + + + + + + + + + + + + @@ -1548,10 +2588,33 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -1564,11 +2627,17 @@ + + + + + + @@ -1580,32 +2649,44 @@ + + + + + + + + + + + + @@ -1614,20 +2695,32 @@ + + + + + + + + + + + + @@ -1641,6 +2734,7 @@ + @@ -1650,58 +2744,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1713,47 +2862,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1761,10 +2946,17 @@ + + + + + + + @@ -1779,6 +2971,7 @@ + @@ -1800,6 +2993,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -1826,33 +3042,49 @@ + + + + + + + + + + + + + + + + @@ -1863,6 +3095,7 @@ + @@ -1871,6 +3104,7 @@ + @@ -1882,23 +3116,45 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -1917,31 +3173,43 @@ + + + + + + + + + + + + @@ -1970,29 +3238,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2004,11 +3362,16 @@ + + + + + @@ -2018,12 +3381,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2036,6881 +3438,12445 @@ - - - + + + + + + - - + + - - + + - - - + + - - + + - - + + - - + + - - + + - - + + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - - + - + - + + + + + + + + + + + + + - + - + - - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - - + + - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - - - + - + + + + + + + + + + - + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + - + - - - - - - - - + + - + - + - + - - - - + - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + - - - - - - - - - - - - - - - + - - - - - - - - - - + - + - - - - - - - - - - - - - + - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - + - + - - - - + - + - - - - - - - - - - + - + - + - + - + - + - - - - + - - - - + - - - - + - - - - - - - - - - - - - + - + + - + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - - + - + + + + + + + + + + + + + - + - + + + + + + + + + + + + + - - + - + + + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - - - - - - - - - - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - + + - - - - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + - + - + - - + + - + - + - + - + - + - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - - - - - - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - - - - - + + + + + + - + - - - - + - + - + + + + - + - - - - - - + - - - - + - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - - - + - + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + + + + + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - + + + + + - + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + - - - + + + - - + + - - + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - + + + + + + + + - - - + + + + + + + + + + + + - - - + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + - - - - + - + - - - - + - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - - - + + + + + + + - - - + + + + - - - + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + + + + + + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - + + + - - - - - - - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -8926,122 +15892,122 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -9050,533 +16016,375 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - - - + + + @@ -9604,1127 +16412,1284 @@ - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -10732,8000 +17697,7447 @@ - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + + + - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + + + - - - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + - + - + - - - - - - + - + - - - - + - - + + - - - - - - - - - + + + + + + + + + - - + + - - - - + + + + - - + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - - - - - - - - - - - - - - + - + - - + + - - - - - - - - - - - - - - - - + + - + + + + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - + + - - + + - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + - - - + + + - - + + - - - - - + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - + - + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - + + + - - + + - - + + - + - + - + - + - - + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - - + + + + + + - + - - - - + + + + + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + + + + + + - - - + + + + + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + + + + + + + - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + + + + + - - - + + + - - - + + + - - - + + + - - + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + - - - - - + + + + + - - + + - - - - - + + + + + + + + + + + + - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + + + + + + + + + + - + + + + - + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - - - - - + + - - - - - - - - - - - - - - - - - - - + - - - - + - + - - - - + - + - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - - - + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + - - - - + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + + + + + + + + - - - + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - - - - - - + + + + + + + + + + + + + + + - - - + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + + + + + - + + + + + - - + + - - - + + + - - - + + + + + + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - - + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + - + - - + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + - - + + - + - + - - - + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - + + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + - - + + + + + + + - - - + + + - - + + + + + + + - - - + + + - - + + - - + + + + + + + - - - + + + + + + + + - - - + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + - + - + - + + + + - + - - + + - - + + - - - - - - - - - - - - - - + + - + + + + - + - + + + + - + - - + + - - + + + + + - + - + - + - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + - - + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + + + - - - - + + + + - - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - + + - + - - + + - - + + - - + + + + + + + + + + + + + + + + + - + - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + - - - - + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - - - - - + + - - - - + + + + + + + + + + + + + + + - - - - + + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - - - + + + - + - - - - + + + + - - - - + + + + - - - - + + + + - - + + + + + + - + - - - + + + - - - - - - + + + + + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - + - + - + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + + + + + + - - + + + + + + + + + + + + + + + - - + + - - - + + + - + - + - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + - + - + - - + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + + + + + + - - - + + + - - - + + + + + + + + + - - - + + + - - + + + + + + - - - + + + - - - - + + + + - - + + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - - - + + + - - + + + + + + + - - + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + + + + + + - - + + + + + + + + + + + - - + + - - - + + + - - - + + + + + + + + + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + - - - + + + - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + - - - + + + - - + + - - + + + + + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + - - - - - - + + + + + + - - + + - - + + + + + + + + - - + + + + + + + + - - - + + + + + + + + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - - + + + - - + + - - + + - - + + - + - + - + + + + + + + + + + + + + - - - - + - - - - + - - - - + - - - - + - + - + - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -18767,1702 +25179,1235 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - - - - - + + + + + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + - + - - + + - + - - + + - + - + - - - - - - - - - - + - + + + + - + + + + - - - - - - - + - + - - + + - - + + + + + + + + - - - - - - - - - - + - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - - - - - - - - - - - - - - - + - + - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - + - - - - + - - - - - - - + - - - - - - - - - - + - - - - - - - + - + + + + + + + + + + + + + + + + - + - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -20470,563 +26415,560 @@ - + - + - + - + - + - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + @@ -21036,3103 +26978,2922 @@ - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + - + - - + + - - + + - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - + - - - + + + + + + + + - - + + - + - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - + + + - - - + + + + + - - - - - + + + + - - - - + + + + + - - - + + + + + - - - + + + + + + - - - - + + + + + - - - + + + + + + + + - - - - + + + - - - - + + + + - - - + + + + - - - - + + + - - - - + + + + - - - - + + + - - - + + + + + + - - - - + + + + + + + + + + + + + + - - - - - + + + + - - - - - + + + + - - - - + + + + + + - - - + + + + + - - - + + + + - - - - + + + - - - - + + + + + - - - + + + + + - - - - + + + + + + + - - - - + + + + + + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + - - - - - + + + + - - - - + + + - - - - + + + - - - - + + + - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - - - + + + + - - + + + + + + - - - + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - + - - - - - - - - - - - - - + - + - + - + - - + + - - + + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - + + + + + + - - - + + + - + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + + + + + - - - + + + - - - - - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + + + + + + + + - + + + + - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - + + - - + + - + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - - - - - - - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - + + - - - - + + + + - - - + + + + + + + + - - - - + + + + - - - + + + - + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - + - + - + - + - + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + + + + + + + + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + @@ -24141,83 +29902,89 @@ - - - - - + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -24232,1697 +29999,1747 @@ - - - + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + + + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + + + + + + + - - + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + - - - + + + - - - - - + + + + + + + + + - - - - + + + + - - + + + + + + - - + + - - + + - - + + + + + + + + + - + - - - - + + + + - - - - - - - - - + + + + + + + + + - + - - - - - - + + + + + + - + - - - - - + + + + + - + - - - - + + + + - + - + - + - + - + - + - + - + - - + + - - + + - - - - + + + + + + + + + - - + + - - + + - + - + - + - + - - - + + + - - - - - - + + + + + + + + + + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - - + + + + + + + + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + + + + + + + + + + + + + + + + - - + + - + - - + + - - - + + + - - + + - - - - - - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -25936,8 +31753,8 @@ - - + + @@ -25949,8 +31766,8 @@ - - + + @@ -26023,674 +31840,645 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + + + + - - - + + + + + + + + + + + + + + - - - + + + + + - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + + + + + + + + + + + + + + + - - - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - + + + + + + + + - - - + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + + + + + + + - - - - - + + + + + - + - + - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -26727,54 +32515,54 @@ - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + @@ -26782,93 +32570,93 @@ - - + + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -26876,271 +32664,275 @@ - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - + + + - - + + - + - + - + - - + + @@ -27167,1255 +32959,1734 @@ - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + + - - - + + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - + + + + - + - - + + - - + + - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - + + + - - + + - - - + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - - - + + + + + + + + + - - - + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + + + + + + - - - + + + - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - + - - - - + - + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + - + + + + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - + + + + + - - - - - + + - - - + + + + - - - + + + - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + + + - - - - - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + - - + + + + + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + @@ -28426,828 +34697,2041 @@ - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + + + + + + + + + - + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + - - - - + + + + + + + - - - + + + + + + + - - - + + + + - - - + + + - - - - - + + + - - - - + + + - - - + + + + + - - - - + + + + - - - - + + + - - - - - - + + + + - - - - - + + + + - - - - + + + + - - - + + + + + + - - - - + + + + + + - - - - + + + + + - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + - + + - + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - - + + - - + + - - - - + + + + - - - + + + - - - - - - + + + + + + + + + + + + + - - - - - + + + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -29259,4049 +36743,11062 @@ - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - - + + + + + + + + + + - - + + - - + + - - + + - - - - - - - - - + + + + + + + + + - - + + - - + + - - - - + + + + - - - - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + + + + + + + - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - - - + + + - + + + + + + + + + + + + + + - - + + - - - + + + + + + + + + + + - - - + + + + + + + - - - + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + + + + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + - + + + + + + + + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + - + - - - - - - - + - - - - - - - - - + - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - - + + + - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - + - + - + - - - - - - - - - - + - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - - - + + + - - + + + + + + - - + + - - + + - - - - + + + + - - - + + + - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + - + - + - + - - - - - - - - - - + - + - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + - - - - + - + - - + + - + - - + + - - - - - + + - + + + + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + + + + - + + + + + + + + + + + + + + + + - - - - + - - - - - - - - - - - - - - - - + - + + + + - + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - + - + - + - + - + - + - + + + + - + + + + - + + + + + + + + + + + + + + + - + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - + - + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + - + - + - - + + - + + + + + + + + + + + + + + + - + - + - - + + @@ -33309,9 +47806,9 @@ - - - + + + @@ -33338,2102 +47835,2133 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + + + + + + + + - - + + - - + + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + - - - - + - + + + + - - - - + - + - - - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + + + + + + + + + + + + - + - - - - + - + - + - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - + - - - - + - - - - - - - + - + - - + + - - - - - - - - + + - + - - - - - - + - - - - + - - - - + - + - + - + - + - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - + - + - - - - - - - - - + - + - + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -35461,8 +49989,8 @@ - - + + @@ -35488,3272 +50016,3309 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - + - + + + + - + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - - + + + + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + + + + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + - + - + - + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -38764,8 +53329,8 @@ - - + + @@ -38774,560 +53339,596 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - + - + - + + + + + + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -39335,1533 +53936,1419 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - + - - - + + + - + - - + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - + - + - - - + + + - - - + + + - - - - - - + + + + + - - - + + + + + + - - - + + + - - - - - - + + + + + + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - + - + - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - + + - + - - - - + + + + - - + + + + + + + + + + + + + + - + - + - + - + - + - - + + - - - - - + + + + + - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + - - + + + + + + + + + + + + + + + - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + + + + + + + - - - - + + + + + + + + + + - - - - + + + + - - - - + + + + - - + + + + + + + + + + + + + - - + + - - - + + + @@ -40869,82 +55356,66 @@ - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + + + + + - - - - - - - - - - + + - - + + - - - - - - - - - - - - - - + + @@ -40952,69 +55423,74 @@ - + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -41034,976 +55510,411 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + @@ -42011,1252 +55922,1433 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + - - - - - + + + + - - - + + + + + + - - - - - - - + + + + + - - - - - - - + + + + + - - - + + + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + - - - + + + + + + - - - - + + + + + + - - - - - - + + + + + + + + - - - - - + + + + + + + + - - - - - + + + - - - - - - - + + + + + - - - - - + + + + + + - - - - - + + + + - - - + + + + + + - - - - - - + + + + - - - - - - + + + - - - - - - - - + + + + + + + - - - - - - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + - - + + + + + + + - - - - + + + + - - - + + + - - + + - - + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + + + + + + - - + + - - - + + + - - + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + + - - - - - - + + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - + + + + + + - - + + - - - - - - + + + + + + + + + + - - - + + + - - - - + + + + + + + + + - - + + - - + + - + - + - - - + + + + + - - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - + + - - + + - - + + - - - - + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - - - + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + + + + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -43283,4011 +57375,4224 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - + + - - + + - - - - - - + + + + + + - - + + - - - - - - - - + + + + + + + + - - - + + + - - + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - - + + + - + - - - - + + + + + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + - - - + + + - - + + - - + + - - - - - - - - + + + + + + + + - - + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + + + + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - - - - - - - - - + - + - + - + + + + + + + + + + - - + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + + + + + - - - + + + - - - - + + + + - - - + + + + + + + + + + + - - - + + + + + + + + + + + + - - + + + + + + + + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + - - - + + + - - + + - - - + + + + + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + + + + + + - - - + + + - - + + - - + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - + + + + + + + + - - - + + + - - - - - - + + + + + + + + + + + + + + + + + + + + - + - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - + + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + + + + + + + + + + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + - + + + + - + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + - + + + + + + + - - + + + + + + + + @@ -47298,1140 +61603,938 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + - - + + - - + + - - + + - + - + - + - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + @@ -48440,266 +62543,269 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - - + + - + - + - + - + - + - + - + - + - - + + @@ -48714,1527 +62820,2834 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - - - - - - - - + + - + - - + + - - + + - - + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + + - - - + + + + + + - - - - + + + + + + - - - + + + - - - + + + + - - - + + + - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + + - - - + + + - - - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + - - - - + + + + + + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - - - + + + + + + + + + + + + + + - + - - + + - - + + - - - - - - - - - - - - - - - - - + + - - - - + - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - + - + + + + - + - + - - - - - + + - + + + + - + + + + - + - + - + - - - - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + + + + + + + + + + + + + - + - + - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - - - + + + + + + + + + + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - + + + + - - - - + + + - - - - + + + + - - - + + + + - - - + + + - - - - + + + - - - - + + + + - - - - + + + + - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - - - - + + + + + - + - + - + - + + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - + - + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - + - + - + - + - + - - - - + + + + - - - - + + + + + + + + + - - - + + + - - - - + + + + + + + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + - - + + + + + + - - + + @@ -50246,1813 +65659,2084 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - + - + + + + - - - - + - + - + - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - - - - + - + - + - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - + - - - - - - - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - + - + + + + + + + + + - + - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + + + + + + + - - - - - - - - - - - - - + + - - + + - - + + + - - + + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + - + - - + + - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + + + + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - - + + @@ -52061,47 +67745,47 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - - - + + + @@ -52111,145 +67795,145 @@ - - - + + + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -52260,803 +67944,1155 @@ - - + + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - + + + + + - - + + - - - - - + + + + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -53072,2636 +69108,2428 @@ - - + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - + + - - - - - + + + + + - - + + - - + + - - - - - + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - - - - - - - + + - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - - + + - - + + - - - - + - + - + - + - + - + - + - + + + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + - - - + + + - - - + + + + + + + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - - - - - - - - + + - + + + + + + + - + - + - + - - + + + + + - + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + - + - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - + + - + - + - + - - - - + - + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -55715,424 +71543,1471 @@ - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + + + + + - - + + - - - + + + + + + + + - - - + + + + + - - - - + + + + + + - - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + - - - - - + + + - - - - - - + + + + - - - - + + + - - - + + + + - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + + + + - - - + + + - - + + - - + + - - - + + + - + - + - + - + - - + + - + - + - - - + + + - - + + - - + + @@ -56141,967 +73016,1629 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - - - + + - - - - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - + - + - + - - + + - + - + - + - - - - + - + - + - + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -57119,15 +74656,15 @@ - - + + - - + + @@ -57137,8 +74674,8 @@ - - + + @@ -57150,205 +74687,59 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + + @@ -57364,53 +74755,53 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -57421,377 +74812,659 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - - + + + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + + + + + + + - - - - + + + + - - + + - - - - + + + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -57800,65 +75473,65 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + @@ -57867,656 +75540,1568 @@ - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - - - - - - - + + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - + + + + + - - - + + + + + - - - - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + + + - - - + + + + + + + + + + - - - + + + + + + + + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - + - + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - + + - - + + - - + + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -58524,597 +77109,647 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + - - - - - + + - - - + + + - + - - - - + + + + - - - + + + - + - - + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - + - - + + - - - + + + - - - - + + + + - - - + + + - + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + - - - - - - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - + - - - - + + + + - + - - - - - + + + + + - + - + - - - - - + + + + + + + + + + + + - + - + - + - + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -59123,246 +77758,444 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - - - - - + + + + + + + + - - - + + + - - + + - + - - + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - + + + + + + + + + + + + + + + - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - + + @@ -59524,1920 +78357,1808 @@ - - + + - - + + - - + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - + + + - - + + + + + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + + + + + - + - + - + - + - + - + - + - - - + + + - - - + + + - - + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - + + + - - - + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + + + + + + - - - - - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - - + + - - + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - + + - - + + - - + + - - - + + + + + + + + + - + - - - - + + + + - - - + + + + + + + + + + + + - + + + + + + + - - - - - - - + + + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + + - - - - + + + - - - - - - - + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + - + + + + - - + + + + + + + + + + - - - - + + + + - - + + - - + + - + - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - - + + - - + + - + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + + + + + + + + - - - - + + + + + + + + - - + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - - + + + + + + + + + - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + - + - + - + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + - - + + + + + + + + + - - - + + + + + + + + + - - - + + + - + - - - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - + + + + + + - - - + + + + + + + + + + + + + + + + + + - + - + - - + + - - - - - - - + + - - + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + + + + + + - - - + + + - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - + + + + + + + + - - + + - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + @@ -61457,1295 +80178,1203 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + - - + + - - + + - - + + - + + + + + - - + + - - + + - - + + - - + + - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + + + + + + + - - + + - - + + + + - + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - - + + - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - - - - - - - + - - - - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + - + + + + - + - - - - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -62755,2716 +81384,7683 @@ - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - + + + + - + + + + - + + + + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + - + - + + + + - + - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + - + + + + - + + + + - + - + - + - + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + - + - - + + + + + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - + - + - - - - + - + - + - + - + - + - - - - - - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -65476,8946 +89072,5660 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - + + - + - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - - + + + + + - - - - + + + - - - - + + + + - - - + + + + - - - - + + + - - - - + + + - - - - + + + + - - - - + + + + + - - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + + + - - - + + + + - - - + + + - - - - + + + - - - + + + + + + - - - - - + + + - - - - + + + + + - - - - + + + + - - - - + + + - - - + + + - - - - - - - + + + + + - - - - - - + + + - - - - + + + + - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + - - - - + + + + - - - - - + + + + + - - + + - + - + - + - - + + - - - - - - + + + + + + - - - + + + - - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - + - + - + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + - - - - + + + + + + + + + + + + + - - + + - + - + - + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - + + + - - - + + + + + - - - + + + + + + + + + + + + - - - - - + + + + + - - - + + + - - - + + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + + + + + + + + + - - + + + + + + - - + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + + + + + + + + + - + - - - + + + - - - - - - + + + + + + + + + - - + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + - - + + - + - - - - - - + + + + + + - - - + + + + + + + + + + + - - - - - + + + + + - - - + + + - + + + + + + + - - + + - + - - - - + + + + - - + + - + - - + + + + + + + + + + + + - + + + + - + - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - - + + + + + + + + + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + - + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + + - + + + + + + + + + + + - - + + - - - - - + + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + - + + + + + + - - - + + + - - - - - + + + + + - - - + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -74427,3136 +94737,4448 @@ - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - + - + - - - - - - + + + + + + - - + + - - + + - - + + - - - + + + - + - - + + - - + + - - + + - - - + + + + + + + - - - - - + + + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - + + + + + + + + - - - + + + - - - + + + + + - - - - + + + - - - - + + + - - - - + + + + - - - - + + + + - - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + - - - - + + + + - - - - - + + + + - - - - - + + + + - - - + + + - - - - - + + + + - - - + + + - - - + + + - - - - - + + + + - - - - - - - + + + + - - - - + + + + + + - - - + + + + - - - - + + + + + - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - - + + - - + + - + - + - + - - - + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + + + + + + - - - + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - + - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + - + - + - + - - - - - - - - - + + + + + + + - - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + + + - - - - + + + + - - - - - - - + + + + + + - - - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - - - - - - + + + + + + + + + + + + - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - - - - + + + + - - - + + + - - + + - - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + @@ -77569,205 +99191,205 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -77777,239 +99399,239 @@ - - + + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + @@ -78017,1314 +99639,1943 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - + + + + + + - - - + + + - - - - - - - + + + + + + + - - + + - - + + - - + + - - - + + + - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - + + + + - - - - + + + + - - + + + + + + + + - - - - + + + + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - + + + + + + + - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + - - + + - + - - + + - - + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - - - - - - - + - - - - + - + - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + - - - - + - + - - + + - - + + - - - - - - - - - - - - - - + + - + + + + + + + - - - - + - + + + + - + + + + + + + - + - + + + + - + - - + + + + + - - + + @@ -79341,222 +101592,222 @@ - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -79566,16 +101817,16 @@ - + - + - + - - + + @@ -79589,972 +101840,972 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -80567,160 +102818,160 @@ - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -80728,810 +102979,810 @@ - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + @@ -81539,1447 +103790,1435 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - + - + - - - - + - - - - - - - - - - + + @@ -83125,8 +105364,8 @@ - - + + @@ -83413,223 +105652,744 @@ - - + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - + + + + + + + + - - - + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + + - - + + @@ -83643,653 +106403,905 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - + + - + + + + + + + + + + + + + + + + - - - + + + - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + - - - - + + + - - - + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - - + + + + + + + + + - - - + + + - + - + - + - + - + - + - + - - + + - - - - + + + + - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - - + + + + + + + + + - - - + + + - - - + + + + + + + + - - - + + + - - - + + + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + + + + + + + + + + + + + - - + + @@ -84306,99 +107318,240 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + - - + + - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -84414,1171 +107567,1095 @@ - - - - - - - + + + + + + + + + + + - - - + + + + + + + + + + + + + + - + - + - + - + - + - - + + - - - + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - - - + + + + + - - + + - - - + + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - + + + + + + - + - - - - - + + + + + - - - + + + - - - + + + - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - + - + - + + - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + + - - + + - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + @@ -85590,508 +108667,508 @@ - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -86103,261 +109180,261 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -86398,1511 +109475,2403 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + + + + + + + + - - - + + + - - - - - + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - - - + + + + + + + + + - - + + - - - - + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/abi_gki_aarch64_ce5de62e20.xml b/abi_gki_aarch64_5cfdde5ea8.xml similarity index 70% rename from abi_gki_aarch64_ce5de62e20.xml rename to abi_gki_aarch64_5cfdde5ea8.xml index ecadc16f9f11..2fca8bd5f473 100644 --- a/abi_gki_aarch64_ce5de62e20.xml +++ b/abi_gki_aarch64_5cfdde5ea8.xml @@ -44,7 +44,6 @@ - @@ -75,6 +74,8 @@ + + @@ -116,6 +117,7 @@ + @@ -146,7 +148,6 @@ - @@ -242,6 +243,7 @@ + @@ -454,7 +456,6 @@ - @@ -627,7 +628,10 @@ + + + @@ -994,6 +998,10 @@ + + + + @@ -1045,8 +1053,23 @@ + + + + + + + + + + + + + + + @@ -1685,8 +1708,6 @@ - - @@ -1709,6 +1730,7 @@ + @@ -1866,6 +1888,17 @@ + + + + + + + + + + + @@ -1873,6 +1906,15 @@ + + + + + + + + + @@ -2103,6 +2145,8 @@ + + @@ -2232,6 +2276,19 @@ + + + + + + + + + + + + + @@ -2289,6 +2346,7 @@ + @@ -2298,6 +2356,7 @@ + @@ -2372,6 +2431,7 @@ + @@ -2392,6 +2452,7 @@ + @@ -2547,29 +2608,29 @@ - - + + - - - + + + - + - + - + - + @@ -2593,9 +2654,9 @@ - + - + @@ -2850,7 +2911,7 @@ - + @@ -2872,7 +2933,7 @@ - + @@ -2906,1425 +2967,1471 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + - + - - + + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - - + + - + - - - + + + - + - + - + - - + + - + - + - + - + - - - + + + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + - + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + - + - - + + - - - - - - - - - - - + + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - + + - + - + - - + + - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + + + + - + - + - + - + - + - - - - + - + + + + - - - - + - + - - - - - - - - + + - + - + - + - + - + + + + - - - - + - + + + + - + + + + - + - + - - + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - + - + + + + - + - + + + + + + + + + + + + + - + - + - + + + + + + + - + - - - - - - - - + + - + - + - - - - - - - - - - - - - + - - - - + - + - - - - - + + - + - - - - + - + + + + - + - + - + - + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + - + - + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - + - + @@ -4332,387 +4439,399 @@ - + - + - + - + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -4720,1194 +4839,1269 @@ - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - - - + + + - + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + - + + + + + + + - + - + + + + - + - + + + + + + + + + + + + + - - - - + - - - - + - + - - + + + + + + + + + + + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + + + + + + + + + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - + - + - + - + - - + + - - + + - + + + + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -5915,646 +6109,679 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - - - + + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - + - - - - - - - - - - + - + - + - + - + + + + + + + + + + + + + + + + + + + - + - + - - - - + + - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -6562,312 +6789,312 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -6887,266 +7114,266 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - + - - - - + - + - + - + + + + - + - - + + - - + + - - + + - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - - - - - - - - - - + + - + - - + + - - + + - - + + - - + + + + + + + + - + - - + + - + - - + + - + + + + - - + + - - + + - + @@ -7154,475 +7381,487 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - + - + + + + + + + + + + + + + - + - + - + - - + + - - + + - + - - + + - - - - - + + - + - - - - - - - - + + - + - - + + - - + + + + + + + + + + + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + - + - + - - + + + + + - - - - - - - - - - + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + @@ -7630,49 +7869,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -7680,608 +7919,608 @@ - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + @@ -8293,588 +8532,613 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - - - + - + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - + + + + - + - - - - - - + - - - - + - + + + + + + + + + + + + - + + + + + + + + + + + + + + + - + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -8884,228 +9148,228 @@ - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -9117,589 +9381,637 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - + - + + + + - - - - + - + - + - + - + - + + + + - - - - + - + - + - + - - - - + - + - + + + + + + + - - - - + - + - + - + - + + + + + + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - - + + - + @@ -9710,15 +10022,15 @@ - + - + - + @@ -9727,527 +10039,527 @@ - - - + + + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + - + - + + + + - + + + + - + - + - + - + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -10259,667 +10571,679 @@ - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + - + + + + + + + + + + - + + + + - + + + + - + + + + - + + + + - + + + + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + @@ -10927,22 +11251,22 @@ - - + + - + - - + + - + - + @@ -10953,7 +11277,7 @@ - + @@ -10970,7 +11294,7 @@ - + @@ -10995,7 +11319,7 @@ - + @@ -11112,7 +11436,7 @@ - + @@ -11121,13 +11445,13 @@ - + - + - + @@ -11135,312 +11459,312 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + @@ -11469,15 +11793,15 @@ - + - + - + @@ -11506,23 +11830,23 @@ - + - + - + - + - + - + - + @@ -11530,46 +11854,46 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -11583,413 +11907,425 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - - - - - - - - - + + - + + + + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + - + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -12001,301 +12337,301 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + - + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + - + - - + + - - + + - - + + - - + + - - - - - - - + - + + + + + + + + + + + + + - + - + + + + - - + + - - + + - - + + - - + + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + @@ -12304,7 +12640,7 @@ - + @@ -12313,964 +12649,988 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -13296,688 +13656,688 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - - - + - + + + + - + - - - - - - - - - - - + + - + + + + - + + + + + + + - + - - + + - - + + - - - - - + + - + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - + - + - + - + + + + + + + - + - - - - - - - - - - + - + + + + + + + + + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + @@ -13988,347 +14348,347 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -14412,10 +14772,10 @@ - + - + @@ -14427,329 +14787,329 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -14769,572 +15129,584 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + + + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + @@ -15342,459 +15714,471 @@ - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -15929,103 +16313,103 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - - - + + + + - + @@ -16034,173 +16418,173 @@ - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -16214,51 +16598,51 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -16420,61 +16804,61 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -16483,8 +16867,8 @@ - - + + @@ -16493,25 +16877,25 @@ - + - + - + - + - + - + - - + + @@ -16520,1235 +16904,1233 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + + - - - - + + + + - - - - - - - + + + + - - + + - - + + - - + + - + - - - - - - + + + + + + - - + + - - + + - + - + - + - + - - + + - + - + - + - + - - - + + + - + + + + - - + + - - + + - + - + - + - - - - - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - - + + + - - - - + + + + - - + + - - - - + + + + - + - - - - - - - - + + + + + + + + - - - + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - + + + - + - + - + - + - - - + + + - - + + - - - - + + + + - + - - + + @@ -17757,3474 +18139,3490 @@ - + - - - + + + - - - - - + + + + + - + - + - - + + - - + + - - + + - + - + - + - + - + - - + + - + - + - - + + - - + + - + - - + + - + - - - - - + + + + + - - - - + + + + - + - + - - - + + + - - - - + + + + - - + + - - + + - + - - - + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - + + + + - - - + + + + + - - - + + + + + - - - + + + + - - - - - + + + - - - + + + - - - - + + + + + - - - - + + + - - - + + + + - - + + + - - - - - - - - - - - - - - - - - - + + - - - + + - - - - + - - - + + + - - - + + + + + - - - - - + + + - - - - - + + + - - + + + + - - - - + + + - - - - + + + - - + + + + + - - - - - + + + + + + + + + - - - + + + + - - - + + + + - - + + - - - - - - - - - - + + + + + - - - - - + + + - - - - - - - + + + - - - - - - + + - - - + + + - - - + + + + + - - - - - + + + + + - - - + + + + + + + - - - - - - - - + + + + + + - - - - - - - - - - + + + - - - + + + - - + + + + + - - + + + - - - - + + + + + + + + - - - + + + + + + + + + + - - - - + + + - - - + + - - - + + - - + + + + - - - + + + - - - + + + + - - - + + + - - - - - - - + + + - - + + - - + + + - - - - - + + + - - - - - - - - + + + - - - - - - - - + + + + + + + - - - + + - - - - + + - - - - - + + + + + - - - - - + + + + + + + + - - - + + + + + + + + - - - + + + - - - - - + + + + - - - + + + + + - - - + + + + + - - - - + + + - - + + + - - + + + + + - - - - - - + + + - - + + + - - - + + + + - - - - + + - - - - - - + + - - - - - - + + + + + + - - - - + + - - - - - + + + - - - - - + + + + - - - - - + + + + + + - - - + + + + + + - - - + + + + - - - + + + + + - + + - - + + - - - + + + + + - - - - + + + - - - + + + - - + + + - - - - + + + + - - + + + - - - - + + + + - - - - + + + - - - - + + - - - + + + + - - - + + - - - - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + - - - - - + + + - - - - + + + + + + + - - - - - + + + + - - + + + + - - - - + + + + - - - - + + + + + - - + + + + - - - + + + + + - - - - - + + - - - + + + + - - - + + + + + + + + - - - - + + + + + + + + + + - - + + + - - - - - - + + + - - - - - - - + + + + - - - + + - - - - + + - - - + + - - + + + - - - + + - - - + + + - - - - - - + + + + - - - + + + - - - - + + - - - + + + - - - - + + + - - - + + + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + - - - - + + + - - + + + + - - + + + + - - - - + + + + + + + + + - - - + + + - - - - + + + + - - - - + + - - - - + + - - + + + + - - - + + + - - - - - - + + + + - - + + + + - - - - + + + + + - - - + + + - - - - - - + + + + - - - - - + + + + + + + - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + - - - + + + + + + + - - - - + + + + - - - - - + + + - - - - - + + + - - - + - - - + + - - - - - - + + + - - - - - - - + + + + - - - - - - - + + + + + - - - - - + + + + + - - - + + + + + + + - - - - + + + + + + - - - - - + + + + + + + - - - - + + + + + + + - - - - - + + + + + - - - - - - + + + - - + + - - - + - - - - - - + + + + + - - + + + + - + + + + + - - - + + + + + + - - - - + + + + + + - - - - + + + + + + - - + + - - - + + + + + + - - - + + + + - - + + + + - - - - - - + + - - - - - - - + + + - - - - - + + + + + + + - - + + + + + + - - + + + - - - - - - + + + - - - - - - - - + + + + + - - - + + - - - + + - - - + + + + + + - - + + - - - + + + + - - + + + - - + + + - - - + + - - - - - + + - - + + + - - - + + - - + + - - + + + - - - - + + + + + - - - + + - - - + + + - - + + - - + + - - + + + + - - - - + + + - - + + + - - - + + - - - + + - - + + - - + + + + - - - + + - - + + + - - - - - - - + + + - - + + - - - + + - - + + + - - + + - - - + + + + + + + - - - + + - - - + + + - - - + + - - + + - - - + + + - - - + + + - - - - + + + - - + + + - - + + - - - - + + + - - + + + - - - - + + + + - - + + - - + + - - + + + + - - - + + - - + + + + - - + + - - - - + + - - - - - - - - + + - - + + + - - - + + - - - + + - - - - + + + + - - - + + + + + + + + - - + + - - - + + + - - + + + - - - - - - - - + + + + - - - + + + - - - - + + - - - - + + + - - - + + - - - + + + + + + + + - - + + + - - + + + + - - + + + + - - + + + - - - + + + - - - + + - - + + - - - - + + - - + + - - - - - - - - + + + - - + + + + - - + + + - + - + + + + + + + - - - - + - - - + - - - - + + + - - - - - - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - - - - + + + + + - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - - + + - - + + + + - - + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - + - + - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - + + + + + + + + - - - - - + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + + + + + - - - + + + - - + + - + - - - - + + + + - - - + + + - + - - - + + + - - - - + + + + - + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - + - + - - + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - + + + - - - - - - - - - - + + + - - + + + - - - + + + + + + + + + + + + + + + + - - - - - + + - - - - - - + + - - - - - + + - - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - + - + - + - - - - - - - + - + - + - + - - - - + - + - + + + + - + - + + + + + + + - - - + + + - + - - - + + + - - + + - - - - - - - - + + + + + + + + - - - + + + - + - - + + - - - - + + + + - - + + - + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - - + + - + - - - - + + + + - - - + + + - - + + - - - - - - - + + + + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + - - - - - + + + + + - + - - - - - + + + + + - - - - - - + + + + + + - - + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + + + + + + + + + - - - + + + - - + + - + - + - + - + - + - - - - - + - + - - - + + + - - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + - - + + - + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - + + - - - - + + + + - - + + - - - - + + + + - + - + - - + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - + + @@ -21232,58 +21630,58 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -21292,543 +21690,543 @@ - - + + - - + + - + - + - - - + + + - + - - + + - - - + + + - + - - + + - - + + - + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - + - + - - + + - + - + - + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - + + - + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - + + - - + + - + - - - - + + + + - - + + - - + + - - - + + + - - + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - + + + + + + + + + + - - - + + + - + - + - + - + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - + + - + - - + + - - - + + + - - + + - - - + + + - + - - + + - - - - - + + + + + - - - - - + + + + + - - + + - - - - + + + + - + - - - + + + - - + + - + - + - + - + - - - - - - - + + + + + + + - + - + - + - + - + - + - - - + + + - - + + - - + + - - + + - + - + - + - - + + - - + + @@ -21840,489 +22238,489 @@ - + - + - + - + - + - - + + - - + + - - - + + + - - + + - + - - + + - - - + + + - + - - - + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - - + + - + - - + + - - - - + + + + - + - - - - + + + + - + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - + - - - - - + + + + + - - - - + + + + - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - + - + + + + - + + + + - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + + - - + + - - - + + + - + - - - + + + - - + + - - - + + + - + - - - + + + - - + + - - - + + + - + @@ -22330,32 +22728,32 @@ - - + + - + - + - + - + - + - + - + - - + + @@ -22370,8 +22768,8 @@ - - + + @@ -22380,708 +22778,713 @@ - + - + - - - + + + + - + - + - + - + - - - + + + - + - - + + - - - - - - - - + + + + + + + + - + - + - + + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - - + + + + - + - - + + - - - + + + - - + + - - - + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - - - + + + + + - - + + - - + + - - - + + + - + - + - - + + - - + + - + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - - - + + + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - + + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - + + + - - - - + + + + - - + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + @@ -23118,76 +23521,76 @@ - - + + - - + + - - + + - + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - + + - - + + - + @@ -23195,857 +23598,864 @@ - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - + + + + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - + + - + - + - - + + - - + + - - + + - - - + + + - - + + - + - - + + - - - + + + - - + + + + + + + + + - - + + - - - - - + + + + + - + - - - - - - + + + + + + - - - - - + + + + + - - + + - - + + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + @@ -24065,452 +24475,452 @@ - + - + - + - + - + - + - + - + - - - + + + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + - - - + + + + + + + + + + - - + + + + + + - - - + + - - - + + + - - - + + + - - - - - - + + + - - - + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - - - + + + + - - + + - - - + + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - + + - + - + - + - + - + - - - - + + + + - + - + - - - - - + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + @@ -24519,199 +24929,199 @@ - - + + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + @@ -24722,70 +25132,70 @@ - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + @@ -24793,21 +25203,21 @@ - + - + - + - + - + - + @@ -24827,7 +25237,7 @@ - + @@ -24847,7 +25257,7 @@ - + @@ -24864,437 +25274,437 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - + + + + - - - - - - + + + + - - - + + + - - + + + + + + + + + + + - - + + + + - - - + + + + + + + - - - - - + + + + + + + - - - - + + + + - - - + + + - - - - + + + - - - - + + + - - - - - - - - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - - - + + + + - - + + - + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - + + - + - - - + + + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - + + + + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - + + - + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - + + - - + + @@ -25312,112 +25722,112 @@ - - - - + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - + @@ -25426,330 +25836,330 @@ - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - - + + - - + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -25777,8 +26187,8 @@ - - + + @@ -25804,113 +26214,113 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -25948,7 +26358,7 @@ - + @@ -25956,7 +26366,7 @@ - + @@ -25994,7 +26404,7 @@ - + @@ -26008,7 +26418,7 @@ - + @@ -26019,7 +26429,7 @@ - + @@ -26039,7 +26449,7 @@ - + @@ -26047,7 +26457,7 @@ - + @@ -26076,57 +26486,57 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -26135,78 +26545,78 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -26217,15 +26627,15 @@ - + - + - - - + + + @@ -26253,118 +26663,118 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -26382,695 +26792,695 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -27094,10 +27504,10 @@ - + - + @@ -27139,7 +27549,7 @@ - + @@ -27174,171 +27584,165 @@ - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -27347,161 +27751,161 @@ - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - - + + - + - - + + - + - + - + - - + + - + - + - + - + - + @@ -27575,12 +27979,12 @@ - + - + @@ -27607,10 +28011,10 @@ - + - + @@ -27636,16 +28040,16 @@ - + - + - + - - + + @@ -27661,21 +28065,21 @@ - + - + - + - + - + - + @@ -27683,13 +28087,13 @@ - + - + - + @@ -27698,59 +28102,59 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -27759,9 +28163,9 @@ - + - + @@ -27769,7 +28173,7 @@ - + @@ -27777,7 +28181,7 @@ - + @@ -27838,7 +28242,7 @@ - + @@ -27851,7 +28255,7 @@ - + @@ -27867,9 +28271,9 @@ - + - + @@ -27880,7 +28284,7 @@ - + @@ -27899,42 +28303,42 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -27943,280 +28347,280 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -28236,7 +28640,7 @@ - + @@ -28254,7 +28658,7 @@ - + @@ -28265,10 +28669,10 @@ - + - + @@ -28279,10 +28683,10 @@ - + - + @@ -28296,10 +28700,10 @@ - + - + @@ -28370,7 +28774,7 @@ - + @@ -28399,7 +28803,7 @@ - + @@ -28413,7 +28817,7 @@ - + @@ -28430,14 +28834,14 @@ - - + + - + @@ -28448,7 +28852,7 @@ - + @@ -28459,30 +28863,30 @@ - + - + - + - + - + - + - + - + @@ -28491,91 +28895,91 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + @@ -28587,46 +28991,46 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -28635,35 +29039,35 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -28671,7 +29075,7 @@ - + @@ -28682,7 +29086,7 @@ - + @@ -28711,7 +29115,7 @@ - + @@ -28725,10 +29129,10 @@ - + - + @@ -28736,7 +29140,7 @@ - + @@ -28751,7 +29155,7 @@ - + @@ -28762,10 +29166,10 @@ - + - + @@ -28794,7 +29198,7 @@ - + @@ -28808,18 +29212,18 @@ - + - + - + - + - + @@ -28848,7 +29252,7 @@ - + @@ -28857,24 +29261,24 @@ - + - + - + - + - + - + - + @@ -28888,190 +29292,190 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -29088,1136 +29492,1136 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + - + + + + + + + - + - + - - + + - - + + - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -30226,960 +30630,960 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + - + + + + - + + + + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - - - - + - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -31191,36 +31595,36 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -31246,58 +31650,58 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -31305,57 +31709,57 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -31363,165 +31767,165 @@ - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -31529,7 +31933,7 @@ - + @@ -31543,28 +31947,28 @@ - + - + - + - + - + - + - + - + - + @@ -31576,16 +31980,16 @@ - + - + - + - - + + @@ -31595,13 +31999,13 @@ - - + + - - + + @@ -31609,20 +32013,20 @@ - - + + - - + + - - + + @@ -31639,15 +32043,15 @@ - - + + - - + + @@ -31657,1934 +32061,1934 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + + - - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - + - + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - + + + - - - - + + + + - - - - - + + + - - + + + + + + + - - - + + + - - - - + + + - - - - + + + + + + - - - - - + + + + - - - + + + + + - - - - + + - - - - - + + + - - - - + + + + - - - - - + + + + - - - - + + + + + - - - - + + + - - - - + + + + - - + + + + + - - - + + + + - - - + + + + + - - - - - - - - + + + + - - - - + + + + - - - - - - + + + + - - - - - - - - + + - - - - - + + - - - - - - - - - - - + + + - - - - + + + + + + + + - - - - - - - + + + + - - + + + + + + - - - - + + + + + + + + - - - + + + + + + - - - - + + + + + + + + + + + - - - - - + + + + - - - - - + + + + + + + - - - - - - - + + - - - + + + + - - - - + + + - - - + + + + - - - + + + + + - - - + + + + + - - - - + + + + + + + - - - + + + - - - - + + + + - + - + - + - + - - - + + + - + - + + - + - + - - - + + + + - - - + + + - + - - + - - - + + + - - - + + + - - - + + + - - - - + + + - - - + + + - - - - + + + + - - + - + - - - - + + + - - - - - + + + - - - - + + + + - - - - + + + - - - - + + + + - - - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + - - - + + + + - - - + + + + + + - - - + + + + - - - - + + + + + - - - - - - + + + + - - - + + + + + - - - + + + - - - - - + + + - - - - + + + - - - - - + + + + - - - + + + + + + - - - - + + + - - - + + + - - - + + + + + - - - + + + + - - - - + + + + + - - - - + + + - - - + + + + - - - - - + + + - - - - - - + + + - - - + + + - - + + + + - - - - + + + + - - - + + + - - - - + + + + + - - - + + + + + + - - - - + + + - - - - - + + - - - - + + + + - - - - + + + - - - - - - - + + + + - - - + + + - - - - - - + + + + - - - - - - - - - + + + + + - - - - - - - + + + + - - + + + + - - - - - - + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - + + + + + + - - - + + + + + + + - - - + + + + - - - + + + - - - - - + + + + + + + + - - - - - - - + + - - - - - - - - - - - - - - - - - - + + + + - - - - - - - + + - - + + + - - - + + + - - - + + - - - - + + + - - + + + + - - - + + + + + + + - - + + - - - - + + + - - - + + + + + + + + + + + + + + + + + + - + + - - + + + + - - - - - - - - - - - - - - - - - - + + + - - - + - - - + + - - - + + + - - + + + - - - + + + + - - - - + + - - - + + + - - + + + - - - - + + + - - - - + + - - - - - - + + + - - - - + + + + - - + + + - - - + + - - + + + + - - - + + + + - - + + + + + - - - + + + + - - - - + + - - - + + + - - - - + + - - - - + + + - - - + + + - - - + + + - - - + + + + - - - + + + - - - + + + + - - - + + + + - - - - + + + - - - + + + - - - + + + - - + + + - - - - + + + - - - - + + + - - - + + + + - - - - - - + + + - - - + + + + + + + - - - + + + - - + + + - - - + - - + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -33593,1248 +33997,1248 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - + - + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + - - - - - - + + + + + - - - - + + + + - - + + + + - - - - + + + - - - - - + + - - - + + + + - - - + + + + + + - - - + + + + - - - + + + - - - - - + + + + + - - - + + + + + + - - - - + + + + - - - + + + + - - - + + + + - - - - + + - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - + + + - - - - - - - - + + + + + + + + - - + + - - - - - - - - - - - + - + - - + + + + + + + + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - - - - - + + + + + + + - + - + - + - + - + - + - - - - - + + + + + - - - - - - - + + + + + + + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + @@ -34842,10 +35246,10 @@ - + - + @@ -34860,10 +35264,10 @@ - + - + @@ -34872,16 +35276,16 @@ - + - + - + - + @@ -34890,13 +35294,13 @@ - + - + - + @@ -34923,16 +35327,16 @@ - + - + - + - + @@ -34941,1333 +35345,1333 @@ - + - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - - + + - - - + + + - - + + - + - - - - - - - - + + + + + + + + - - + + - - - + + + - - + + - - - - + + + + - - + + - + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - - - - - - - - - + + + - - - - - - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - + + + + - - - + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - + - - - + + + - - + + - - - - + + + + - + - + - + - + - + - + - + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - + - + - + - + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - + - + + + + - - - - + - + - + - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - - - - + - + - + - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - + - - - - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -36284,823 +36688,829 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + - + - + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - - - - + + + + + + - + - + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + + + + + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - - - - - - - + + + + + + + + + - - - + + + - - - + + + - - - - + + + + - + - + - - + + - - + + - - + + - + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - + - - - + + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - + - - - - + + + + - - + + - - + + - + - + - + - - - + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + + - - - - - + + + + + - - - + + + - - - + + - - - + + + + + - - - + + + + - - - + + + - - - - + + + + + - - - - + + + - - - + + + + + + + + - - - - + + + - - - - - + + + + - - - - - + + + + + - - - - - - + + + + + - - - - - - + + + + - - - - - - - - + + + + + - - - + + + + - - + + + + - - - + + + + + - - - - - + + + + + - - - + + + - - - + + - - - + + + - - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - + + @@ -37109,171 +37519,171 @@ - - + + - - + + - - - + + + - - - - + + + + - - + + - + - - - - + + + + - - + + - + - + - - + + - + - + - + - + - - - + + + - - - + + + - + - - + + - - + + - - - - - - + + + + + + - - - - - - - + + + + + + + - + - - + + - + - + - + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -37282,8 +37692,8 @@ - - + + @@ -37294,1268 +37704,1283 @@ - + - + - - - - - - - + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - + - - - - - - + + + + + + - - - - - - - + + + + + + + - + - - + + - - - - - + + + + + - - + + - + - - - + + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - + - - + + - - + + - - - - + + + + - - + + - - + + - - - - - + + + + + - + - + - - + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - - + + + - - + + - - + + - - + + - - - + + + - + - - + + - + - + - + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - + - - - + + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + + + + + + + + + - + - - + + - + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - + - - - - - - + + + + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - + - + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - + + + + - + - - - + + + - + - + - + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - - - - + + + + + - - + + - + - - + + - - + + - - - + + + - - + + - - + - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -38564,898 +38989,898 @@ - - - - - + + + + + - - + + - - - - + + + + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - + - - + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - + - - - + + + - + - + - - - - - + + + + + - - + + - + - - - + + + - - + + - + - - + + - - - - + + + + - - + + - - - - + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - - - - - + + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - + - - + + @@ -39479,649 +39904,649 @@ - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - + - - + + - - - - + + + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - + - + - - - + + + - - - - + + + + - - + + - - + + - + - - - + + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - + + + - - - - - + + + + + - - - + + + + + + + + + - - + + - + - + - + - - + + - + - + - + - + - + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - - + + + - + - + - + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - - - - - + + + + + - - + + - - - - - + + + + + - - + + - - + + - - + + - + - + - + - - - - - + + + + + - - + + - - - + + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - + + - - - - - + + + + + - + - + - + - - - - + + + + - - + + - - + + @@ -40130,555 +40555,555 @@ - + - - + + - + - - + + - - + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -40686,43 +41111,43 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -40731,297 +41156,297 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -41029,26 +41454,26 @@ - + - + - + - + - + - + - - - + + + @@ -41056,199 +41481,202 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + @@ -41259,7 +41687,7 @@ - + @@ -41280,2324 +41708,2334 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - + - - + + - - + + - - - - + + + + - + - + - - - + + + - - + + - - - - + + + + - - - + + + - + - + - - + + - - - + + + - - - + + + - - - + + + - + - - + + - - + + - + - + - + - + - - - - + + + + - - - - + + + + - + - - + + - - + + - - + + - - + + - - + + - + + - - - - + + + - - - + + + - + - + - + - - - + + + - - - + + + - - + + - - + + - - - - - + + + + + - + - - + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - + + + + + + + + - + - + - + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - - - - - + + - + - - - - + + + + - - + + - - - - - + + - - + + - - - - - - - + + + + - - + + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - - - - + + + + - + - + - + - + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - + + + + - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - + + + - - + + - - - - - + + + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - + - - - + + + - - - - + + + + - - + + - + - + - - + + - - + + - - - - - - - - + + + + + + + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - + - + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - + - + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - + + + - + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - - + + + + + + - - + + + + + + + + + + - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + - + - + - + + + + - + - - + + - - + + - - - - - - - - - - - - - - + + - + + + + - + - + + + + - + - - + + - - + + + + + - + - + - + - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - + - - - + + + - - - + + + - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - + - - - - + + + + - - + + - - - - - - - - - + + + + + + + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + - - + + - - - + + + - - - + + + - - + + - + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - + - + - + - + - + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - + - + - + - + - + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - + - + - - - + + + - - + + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - - + + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - - + + - - + + - + - - + + - - + + - + - + - - + + - - + + - + - + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - - + + - - + + - - - + + + - - - + + + - - + + - + - + - + @@ -43606,915 +44044,915 @@ - + - - + + - - - + + + - + - - + + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - - - + + + + + + - + - + - - - + + + - + - + - - + + - + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - + + - + - + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + + - + - - - + + + - - - + + + - - - + + + - + - + - - - + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - + + + + + - - - - + + + - - - + + + - - - - + + + - - - - - - - + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - + - - + + - - + + - - + + - + - - + + - + - + - - + + - - + + - + - + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - + + - - - + + + - - - + + + - + - - - - - - + + + + + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - + - + - - - + + + - - + + - - + + - - - - - + + + + + - + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - - + + + - - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - + + - + - - - - - + + + + + - - - - - + + + + + - - + + - + - - - + + + - + - + - + - + - + - + - - + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - + - + - + - + - - + + @@ -44522,2516 +44960,2516 @@ - - + + - + - - - + + + - - + + - - - + + + - - + + - - + + - + - - - + + + - - + + - - - + + + - - + + - + - + - - - + + + - - + + - + - - - + + + - - + + - - + + - + - + - + - + - - - + + + - - + + - - + + - - + + - + - + - + - + - + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - + + + + - - - - - - - - + + + - - - - + + + + + + + - - - - + + + + + + + - - - + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - + - - - + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - + - - - + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - - - + + + + + + + + + - + - - + + - + - - - + + + - - + + - - + + - - - + + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - + - + - - + + - - + + - - - + + + - - + + - + - - + + - - + + - - + + - - + + - - - + + + - + - - + + - + - - + + - + - + - + - - + + - + - + - - + + - - + + - - + + - + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - - + + + + + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - + - + - + - + - + - - - + + + - + - + - - - + + + - + - + - + - - + + - + - + - - + + - - + + - + - + - - + + - + - - + + - + - - + + - - - + + + - - - + + + - - - + + + - + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - - + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - + + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - + + + - + - - - - + + + + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + + + - - - + + + - - - + + + + - - - + + + - - - + + + - - - - + + + - - + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + - + - + - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - + + @@ -47039,384 +47477,384 @@ - - + + - + - + - - - + + + - + - - + + - - - + + + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - - + + - + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - - - - - + + + + + + - + - - + + - + - - + + - + - + - + - - + + - + - + - - - + + + - - - + + + - + - + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + - + - + - + - + - + - + - + - - - - - - + + + + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - - - - - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - - - - - - - - - + + + + + + + + + + - - + + - + - + - - + + - - + + - - + + - - + + - + - - - - + + + + @@ -47424,25 +47862,25 @@ - - + + - - + + - - + + - + - - + + @@ -47453,52 +47891,52 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -47509,370 +47947,370 @@ - + - + - + - - - - - - - - + + + + + + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - + - - + + - + - - - - + + + + - + - - + + - - - + + + - - + + - - + + - + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - + + - + - + - - - - - - - - - - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -47881,36 +48319,36 @@ - + - + - + - + - + - + - + - + - + - - + + @@ -47927,1060 +48365,1084 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -48989,60 +49451,60 @@ - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -49063,63 +49525,63 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -49127,75 +49589,75 @@ - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -49224,68 +49686,68 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + @@ -49294,62 +49756,62 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -49358,768 +49820,772 @@ - + - + - + - + - + - - + + - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - - + + - - + + - + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - + - - + + - - + + - + - - + + - + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - - + + + - + - - - - - + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + + + + + - + - - + + - - - + + + - - - - + + + + - + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + - - - + + + + - - - + + + + + - - - - - + + + + - - + + + + + + - - + + + + - - - + + + - - - - - - + + + - - - - - - + + + - - - - + + + - - - - + + + + + - - - - - - - + + - - - - - - + + - - - - + + + - - - + + + + + + - - - - + + + + + + - - - - + + + + - - - + + + + - - + + + + + + + - - - + + + + + + - - - - - - + + + + - - - - - - + + + - - - - + + + + - - - - - + + + + - - - - + + + - - - - - + + - - - + + + - - - - - + + + + + + - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + - - - - - - - - - - - - - - - - - - - + + + + + - - + + - - + + + - - + + + + + + + - - + + + + + + - - - + + + + + + - - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + @@ -50132,68 +50598,68 @@ - - + + - - + + - - - + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -50202,1435 +50668,1435 @@ - + - + - + - + - + - - - - + + + + - - - + + + - - + + - + - + - - + + - - - - + + + + - - + + - + - - + + - - + + - + - + - + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - + + + + - + - - - - + + + + - - + + - - - + + + - + - + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - - - - + + + + + - + - - - - - + + + + + - - - + + + - + - - - + + + - + - - + + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - + + - + - - + + - + - - + + - + - - - + + + - + - - + + - + - - + + - - - + + + - - + + - - - - + + + + - - + + - - + + - + - + - - - - - - - + + + + + + + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - - - - - + + + + + - - + + - - + + - - + + - - - - + + + + - - + + - - - - + + + + - + - - - + + + - - - + + + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + + - - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -51639,476 +52105,476 @@ - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - + + - - - + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - + - + - - + + - + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - + - + - - + + - - + + - - - - - - + + + + + + - + - - - - + + + + - - - - - - + + + + + + - + - - - + + + - + - + - + - + - + - + - - - - + + + + - - + + - - - - + + + + - - - + + + - + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -52116,15 +52582,15 @@ - + - + - + @@ -52141,134 +52607,138 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + + + + + - + - + - + - + @@ -52277,704 +52747,704 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - + + + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + - + - - + + - - - + + + - - + + - + - + - + - + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + - + - + - + - + - - - + + + - + - - - + + + - + - + - - - - - - + + + + + + - - - + + + - - - + + + - - + + @@ -52983,1155 +53453,1155 @@ - - - - - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - + + - + - - - + + + - + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + + + + + + - - + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - + - + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - + - - - + + + - - - - - + + + + + - - - - - + + + + + - + - - - + + + - - - - + + + + - - + + - + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - + - - + + - + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - + - - + + - + - - - + + + - - - - + + + + - - + + - - + + - - - - - - - + + + + + + + - + - + - - + + - - + + - + - - - - - + + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - + - + - - + + - - - + + + - - + + - - - + + + - + - + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - + - + - + - - + + - - - - + + + + - - + + - + - - + + - + - - - - - + + + + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - - - - + + + + + + - - - + + + - + - + - - + + - - - - - - - + + + + + + + - + - - - + + + - - - - + + + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + - - + + - - - + + + - + - - - - + + + + - + - - + + - - + + - - - - + + + + - - - - + + + + - + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + - + - + - - - - - - - - - - - + + + + + + + + + + + - + - - - - - - + + + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -54154,337 +54624,337 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + - + - - - - + + + + - - + + - + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - + - - - - - - - + + + + + + + - - - + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - + - - + + - - + + - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + @@ -54492,7 +54962,7 @@ - + @@ -54506,88 +54976,88 @@ - + - - + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - - + + - + @@ -54595,7 +55065,7 @@ - + @@ -54691,7 +55161,7 @@ - + @@ -54732,507 +55202,507 @@ - - + + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - - - - - + + + + + + + - - - + + + - - - + + + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -55241,8 +55711,8 @@ - - + + @@ -55262,8 +55732,8 @@ - - + + @@ -55377,21 +55847,21 @@ - - + + - + - + - + - - + + @@ -55412,149 +55882,149 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -55562,863 +56032,863 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - + - + - - - + + + - + - - + + - - - - + + + + - - + + - + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - - - - - - + + + + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + - + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - + - - - - + + + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - - - + + + - + - - + + - - + + - - - + + + - + @@ -56429,635 +56899,605 @@ - - + + - - - + + + - - - + + + - - - - - + + + + + - + - - - - + + + + - + - + - + - + - + - + - + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - - + + + + + - - + + - - - - - + + + + + - - - + + + - - + + - + - + - - + + - - - - - - - - - - - - - - - - - - - - + + - + - + - + + + + - + - + - - + + - - + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + - + - - - - + - + + + + + + + + + + - + - + - + - + - + - + - + - - + + - - - - - + + + + + - - - + + + - - + + - + - - - + + + - + - - - - - - + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + - - - + + + + - - + - - + + - + - + - - - - - + + + + + - - + + - - + + - + - + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - + + - + - + - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -57071,7 +57511,7 @@ - + @@ -57080,13 +57520,13 @@ - + - + - + @@ -57101,7 +57541,7 @@ - + @@ -57128,15 +57568,15 @@ - + - + - + @@ -57156,23 +57596,23 @@ - + - + - + - + - + - + - + @@ -57180,724 +57620,736 @@ - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + - + - + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - + + - - + - + - - + + - - - + + + - - + + - + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - + + - - - + + + - - - - - - + + + + + + - - - + + + - + - + - + - + - + - + - + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - - - - - - + + + + + + + + + - + - - - - + + + + - - - - + + + + - + - + - - + + - + - - - + + + - + - - + + - + - - - + + + - - - - + + + + - + - + - + - - + + - - + + - - - - - + + + + + - + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + + + + + + + + + + + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -57906,13 +58358,13 @@ - + - + - + @@ -57920,14 +58372,14 @@ - - + + - + @@ -57935,20 +58387,20 @@ - + - + - + - + - - + + @@ -57957,915 +58409,915 @@ - - - - - - - - + + + + + - - - - - - - + + + + + - - - + + + + - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - - - - - + + + - + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + - - - + + + + + - - - + + + + + + + + + + + + + - - - - - - - - - - - - - + + - - - + + - - + + + + - - - + + + + - - + + + + + + + + + + + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - - - - + + - - + + - + + - - - - - + + + + + + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - + - - + + - - + + - - + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - - - + + + + + + - - + + - - - - - - - - - - - - - - - + + - - - - - - - - - - - - + + + + + - - - - - - - + + + + - - - + + - + + + + + + + + + - - - - - - - - - + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + - - - - + - + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -58874,52 +59326,52 @@ - + - + - + - + - + - + + + + + + - - - - - - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - - + + + + + + - + @@ -58927,97 +59379,97 @@ - + - - - + + + - - + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - + - - + + - - - + + + - - + + - - + + - - - + + + - + - + - + - - - - - + + + + + - + - + - - - + + + - - + + @@ -59053,203 +59505,203 @@ - - - - + + + + - + - - - + + + - - + + - - - + + + - - - - - - - + + + + + + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - - + + + + + - + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - + + @@ -59258,163 +59710,163 @@ - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - + + - - - + + + - + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - - + + - + - - + + @@ -59425,8 +59877,8 @@ - - + + @@ -59438,1762 +59890,1750 @@ - - + + - - - + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - + - - + + - - + + - - - + + + - + - + - + - + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - + - + - - + + - - - - + + + + - - + + - - - + + + - - + + - - - - - + + + + + - - + + - - + + - - - - - - + + + + + + - - + + - - + + - - - + + + - + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - - - + + + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - - + + - - + + - + - - - + + + - - + + - - - + + + - + - - + + - - + + - - + + - - - + + + - + - - + + - - - + + + - - - + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - + + - - - - - - + + + + + + - + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + - + - - + + - - + + - - + + - + - + - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - + - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - + - - - + + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - - + + + + - + - + - + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - - + + @@ -61202,2692 +61642,2787 @@ - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - + + + + + + + - + - + - + - - - - - + + + + + - - + + - + - - - - + + + + - - - + + + - - - - + + + + + - - + + + + + + + - + - - - - - - + + + + + + - - - + + + + - - - + + - - + + - + - - - - - + + + + + - - - + + + - - - + + + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - + - - - - - - + + + + + + - - - - + + + + - + - - + + - - + + - - - - + + + + - - - - - + + + + + - - + + - + - - + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - + + - - - - + + + + - - + + - + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - + - - + + - + - + - - - - - - + + + + + + - - - + + + - + - - - - - + + + + + - + - + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - + - - - + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - + - - - + + + - - - - - - + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - + + - - + + - - - - - + + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - - - - + + + + + - - + + - - + + - + - - + + - - + + - + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - - + + + + - - + + - - + + - + - - - + + + - + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + + + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - - + + + - + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - + - + - + - + - + - - - + + + - - + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - + + + - - + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - - + + - - - + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - - + + + - + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - + - - + + - + - - - - + + + + - - + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - - - + + + + + - + - - + + - - - - - - + + + + + + - - - + + + - + - - - + + + - + - + - - - + + + - + - - + + - - + + - - - + + + - + - + - - + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - + - - - - - - + + + + + + - - - - + + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - + - - + + - + - + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - + + + - + - - + + - - + + - - + + - + - + - + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - - - + + + + + - - - + + + - - - - - - - + + + + + + + - + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - - - + + + - - + + - - - - + + + + - - - - + + + + - + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + @@ -63895,21 +64430,21 @@ - + - + - + - + - + @@ -63918,2354 +64453,2343 @@ - + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - + - - - + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - - + + - - - - - - - - + + - + - + - - + + - - + + - + - + - + - - - - + - + + + + - + - - - - - - - - + + - - - - - - - + - + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - + - + - + - + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - - - + + + + + - - + + - + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - + - + - + - - + + - - + + - + - + - - - - + + + + - - - - + + + + - + - + - - + + - - - - + + + + - + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - + + - + - - + + - - - + + + - - - + + + - + - - - + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - + + + - + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - + - + - + - + - - + + - - - + + + - + - + - - + + - + - + - - + + - - - + + + - + - - - + + + - - - - - + + + + + - - + + - + - + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - + - - - - - + + + + + - - + + - - - - - + + + + + - - - - - - - + + + + + + + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - - - - - - + + + + + - + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - - - - + + + + + + - - + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - + - + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - + - + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - + + - - - - + + + + - - - + + + - + - + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - + - + - + - - + + - - - - + + + + - - - - - - + + + + + + - + - - - - - + + + + + - - - - + + + + - - + + - + - + - + - - + + - - - - + + + + - - - - - + + + + + - + - + - + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - + - + - + - - - + + + - + - - + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - + + - + - - + + - - + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + - - - + + + + + + + + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - - + + - - - + + + - + - + - + - + - + - - - + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - - - - + + + + + + - + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -66279,10 +66803,10 @@ - + - + @@ -66296,254 +66820,254 @@ - + - + - + - + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -66551,676 +67075,699 @@ - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - + + - - + + - - - + + + - + - - - + + + - - - - + + + + - - + + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - + - - - - + + + + - - + + - - - + + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - + - + - - - + + + - - - + + + - + - - - - + + + + - - + + - - - + + + - - - - - - + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - + + + - + - - - - + + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - + + - - - - - - + + + + + + - + - + - + - + - + - + - - + + - + - - + + @@ -67234,913 +67781,1262 @@ - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - - + + - - + + - - + + - - - - + + + + - + - - + + - - - + + + - - + + - - - - - - - + + + + + + + - - + + - - - - + + + + - + - + - + - + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - + + - - + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - + - + - + - + - + - - - - + + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - + + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - + - + - - - - - + + + + + - - + + - - - - + + + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - - + + - + - - - - + + + + - + - - + + - - + + - + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - + - - - + + + - - - + + + - + - + - + - + - + @@ -68149,1374 +69045,1374 @@ - + - + - - - + + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - + + - - - - + + + + - - + + - + - - - + + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - + + + + - + - + - + - - - - - - - - - + - - - + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - - - - - + + + + + - - + + - + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - - - + + + - - - - + + + + - + - - - + + + - + - + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - - - - + + + + + + - + - - - + + + - + - - + + - + - + - + - + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - - + + - - - + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - + - + - + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - + - + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -69525,78 +70421,78 @@ - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -69605,34 +70501,34 @@ - + - + - + - + - + - + - + - - - - + + + + @@ -69643,18 +70539,18 @@ - + - + - + - + - + @@ -69663,45 +70559,45 @@ - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + @@ -69713,35 +70609,35 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -69753,703 +70649,680 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - + - - - - - + + + + + - - - - - - + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + - - - + + + - + - + - + - + - + - + - - + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - + - + - + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - + - - + + - + - + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -70473,13 +71346,13 @@ - + - + - + @@ -70494,181 +71367,181 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -70680,7 +71553,7 @@ - + @@ -70689,22 +71562,22 @@ - + - + - + - + - + @@ -70713,49 +71586,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -70770,82 +71643,82 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -70866,70 +71739,70 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -70940,337 +71813,337 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - - + + + - - + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - + + - + - + - + - + @@ -71282,391 +72155,375 @@ - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - + - + - + - + - + - + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - - - + + + + - + - - - - - + + + + + - - - + + + - - + + - - + + - - - - - - + + + + + + - - - - - + + + + + - + - + - + - - - - - - + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -71674,27 +72531,27 @@ - + - + - + - + - + - + - + @@ -71703,873 +72560,873 @@ - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - - + + - - + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - + - - - + + + - - - - + + + + - - + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - + - + - + - + @@ -72580,7 +73437,7 @@ - + @@ -72597,31 +73454,31 @@ - + - + - + - + - + - + - + - + - - + + @@ -72641,27 +73498,27 @@ - + - + - + - + - + - + - + - + @@ -72678,1747 +73535,1752 @@ - + - + - - - - - - - - - + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - - - - + + + + + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - - - - - - - + + + + + + + + + - - - - - + + + + + - - + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - + - + - + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - + + - + - + - + - + - + - - + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - - - - + + + + - - - - + + + + - - + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - + + + - + - - - + + + - + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - - - + + + - + - + - + - + - + - + - + - + - - + + - - + + - - - - + + + + - + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - + + - - - - - + + + + + - - + + - + - - + + - - + + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - + - + - + - + - + - + - - - - - + + + + + - + - + - + - + - + - + - + - + - - - + + + - - - - + + + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - - - - - - - + + + + + + + + + - - - + + + - + - - - - + + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - - - - - - + + + + + + - - + + - + - - + + - + - - - + + + - - - - + + + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - + + - - + + - + - - - - + + + + - - + + - + - + @@ -74430,1667 +75292,1667 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - - - - - - + + + - - + - - - + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - + + - + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - + + + - + - - + + - + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - + + - + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - + + - - - + + + - - - - + + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -76101,1979 +76963,1964 @@ - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - - + + + - + - + - + - - - + + + - - + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - + + - + - - - + + + - - + + - + - - + + - + - - - + + + - + - - + + - - + + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - - - - + + + + + + + - + - + - + - - - - + + + + - - - + + + - - + + - + - - + + - + - - + + - - + + - - - + + + - - - + + + - + - - + + - - + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - + - - + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - + + + + - + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - + - - + + - - - - - - - + + + + + + + - + - + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - - + + + - + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - + - - + + - - - - - + + + + + - - + + - - - + + + - + - - + + - - + + - + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - - + + + - - + + - + - - - + + + - + - - + + - - - + + + - - + + - + - - - + + + - - + + - + - - - + + + - + - - - + + + - - + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - - - - - - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - + + - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + + + + + - - + + + + + - - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + - - - - - + + + + + - - - - - + + + + - - - - - - - - - - - - - - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + - + - - - - + + - + + + + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + - - + + + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - + - - - - - + + + + + - - + + - + - + - + - + - - + + - + - + - + - + - - - - - - - + + + + + + + - + - + - + - - + + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -78082,145 +78929,145 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -78262,174 +79109,174 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -78438,203 +79285,203 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -78643,51 +79490,51 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -78699,117 +79546,117 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -78822,15 +79669,15 @@ - - + + - - + + @@ -78846,735 +79693,735 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - + - - + + - + - + - + - - - - - - - + + + + + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - - - - - + + + + + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - + - - + + - + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -79583,694 +80430,694 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - + - - + + - + - + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - + - - + + - - - + + + - - - - + + + + - - - + + + - + - - + + - - + + - - + + - + - + - - - - - + + + + + - - + + - - + + - - + + - - - + + + - + - + - + - - + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - + - - - - - + + + + + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - + - + - + - + - + @@ -80282,902 +81129,910 @@ - + - - - + + + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - + - - + + - - + + - - + + - + - + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - + + - + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - + + - - - - - - - - + + + + + + + + - - + + - - - + + + - - + + - + - + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - + - + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - + - + - + - - + + - - - - + + + + - + - - - + + + - - - + + + - - - + + + - + - + - + - - - - - - - + + + + + + + - + - - + + - - - - + + + + - + - - + + - - - - - + + + + + - - + + - - + + - - + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - + - + - + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - + - + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - + + - + - - + + - - - - - - - + + + + + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + + + + + + + + + - - - - + + + + - + - - + + @@ -81189,270 +82044,270 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - - - + + + - + - - - - + + + + - - - - + + + + - - + + - + - - + + - - + + - - + + - + - - - - + + + + - - - + + + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + @@ -81461,558 +82316,558 @@ - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - + + - - + + - + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - + - + - + - - - + + + - - - + + + - - + + - - + + - + - + - + - + - - - + + + - - + + + - - - + + - - + + - - - + + + - + - + - + - - + + - - - - + + + + - - + + - + - + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - + - + - + - + @@ -82020,2085 +82875,2093 @@ - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - - + + + + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - + + - - - + + + - - - + + + - + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - - + + - + - + - - - + + + - + - - + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - + + - + - - + + - - + + - - - + + + - - - + + + - - - - - + + + + + - + - - + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - - + + - + - - + + - + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - + + + + + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + - - - - - + + + - - + + - - - + + - - - - + + - - - - - + + + - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + + - - - + + + + + - - - + + - - - + + + - - - - - - + + + + - - - + + + + + - - - - + + + - - - - - - + + + + + + - - - - - - + + + + - - - - + + + + - - + + + - - + + + - - - - - + + + - - - + + + - - - + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + + - - - - + + + + + + - - - - - + + + + - - - - - - + + - - - - - + + - - - - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + - - - - - + + + + - - - - - + + + + + - - - - - - + + + + - - + + + + + - - - - + + + + + + - - - + + + + + - - - - + + + + + + + - - - - - - + + + + - - - - - + + + + - - - + + + + - - - + + + + + - - - + + + + + - - - - + + + + + + - - - + + - - + + + + - - - + + + - - - + + + + - - - + + + + + + - - - - - + + + + + - - - - + + + - - - - + + + - - - - + + + - - - + + + + - - - - - + + + - - - - + + - - - - - - + + + - - - - + + + - - - - - + + + - - - - + + + + + - - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + - - - + + + + + + - - - - + + + + - - - + + + + + - - - + + + + - - - - + + + + + - - - + + + + - - - - + + + + - - + + + - - - - + + + + + - - - - - + + + + + - - - - - + + + - - + + + + - - - + + + - - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + - - + + + - - + + + - - - - + + + - - - + + + - - - + + - - - + + + - - - + + + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + + + + + + + + + + - + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -84107,244 +84970,262 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + - + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + - - + + - - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -84362,256 +85243,256 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + - - - - + - + + + + - - - - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -84631,1183 +85512,1135 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + + + + + + - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - + + - + - + - + - + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - + - - - - + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - + + - - - - - - - - - + + + + + + + + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - + - + - + - + - - - + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - + + + - - - + + - - - + + - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + - - - - - - - - - - - - - + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - + - - - - - - - + + + + + + + - - - - - - + + + + + + - - + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - - - + + + + + + - - + + - - - + + + - + - + - + - + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - + - - - + + + - - - + + + - + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + + - - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -85822,392 +86655,392 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - + - - + + - - + + - - + + - + @@ -86215,2223 +87048,2230 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - + - - - + + + - - + + - - - + + + - + - - + + - - - + + + + - - + - - - - - + + + + + - - - + + + - - - + + + - + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - + - - - - + + + + - - - + + + - - - - - - + + + + + + - + - - - + + + - - - - + + + + - + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + + + + + + + + - - - + + + - - + + - - + + - + - + - + - + - + - + - - - + + + - - - + + + - - + + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - + + + + + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - + + - + - + - + - - - + + + - - - + + + - - + + - - - - + + + + - + - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - + - - - - + + + + - - - + + + - - - + + + - + - + - + - + - + - + - - + + - + - + - - + + - - + + - + - + - + - + - + - + - - - + + + - - - - + + + + - - - + + + - - - + + + - + - + - + - - - - - + + + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - - - + + + + + - + - - + + - + - + - + - + - + - + - - + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - - - - - - - - - - + + + + + + + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - - - - + + + + + + + - + - - - + + + - - + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - + - + - + - + - + - + - - - - + + + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - + - - - - + + + + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - + - - + + - - - - - + + + + + - - - + + + - - + + - - - + + + - + - + - - + + - + - + - + - + - + - + - + - - - + + + @@ -88441,319 +89281,319 @@ - - + + - + - + - + - - + + + + + + + - - - - - - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + - - - + + + - - + + - - - + + + - + - - - - + + + + - + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - - + + @@ -88830,18 +89670,18 @@ - + - + - + - + - + @@ -88850,1970 +89690,1971 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - + + - - + + - - - - - - - + + + + + + + - + - + - + - + - + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - - - - - + + + + + + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - + - - - - + + + + - - + + - - + + - + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - - + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - - - - - - - - - - - - - - - - + - + - + + + + - + - + + + + + + + - + - - - - - - - - - - - - - + - + - - + + - - + + - - + + - - + + + + + + + + - + - + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - + - + + + + - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + - - - - - - + + + + + + + + + + + + + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - + + + + - - - - - + + - - - + + + + + - - - - - - - + - - - - - + - - + + + + + + + + + - - - - - + + + - - - + + + + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - + - - + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - + - + - - - - + + + + - - + + - - + + - + - - - + + + - - + + - - - + + + - - + + - - - - + + + + - + - + - + - + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - + - + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - + - + + - - + + - - - - - + + + + + - + - + - - - + + + - + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - - + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - + - + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - - - - - + + + + + + - - - - + + + + - + - + - - + + - + - + - + - - + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - + + - + - - - + + + - - - + + + - + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - + - - + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - + - - + + - - + + - - + + - + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - + - + - + - - + + - + - - + + - - - - - + + + + + - - - - + + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + @@ -90821,1569 +91662,1908 @@ - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - - + + + - - - - + + + + - - + + - - + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - + + - + - + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - + - + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - + - - - + + + - - + + - + - - + + - - - + + + - - + + - - - - + + + + - + - + - + - - - - + + + + - - + + - - + + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - + - - - + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - - - - - - - - - - - - - - - - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - + + - + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - + - - - + + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - + - + - + - + - + - + - + - - - - + + + + - - - - + + + + - - + + - + - - - + + + - - + + - + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - + - - - - + + + + + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - + + - + - + - + - + - - + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - + - - - + + + - + - - - + + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - - - - - + + + + + + @@ -92391,445 +93571,445 @@ - - + + - - + + - - + + - + - - + + - - + + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - + + + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - + + + - + - + - + - + - + - - + + - + - + - - - - + + + + - - - + + + - + - + - + - + - - - + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - - - - - - + + + + + + + + @@ -92838,145 +94018,145 @@ - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - + - + - + - + - + - - + + - + - + - + - + - - - + + + - - - + + + @@ -92986,175 +94166,175 @@ - - + + - + - + - + - + - + - + - + - - - + + + - - - - - - - - - + + + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - + + - - - + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -93166,89 +94346,89 @@ - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + @@ -93259,1116 +94439,1116 @@ - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - - - + + + + + + - + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - + + - - - - - - - + + + + + + + - + - + - + - + - + - + - - - + + + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - + + - + - + - + - + - + - + - - + + - - - - + + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - + - + - + - + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -94388,459 +95568,459 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -94867,312 +96047,312 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -95180,991 +96360,991 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + + - - - + + + - - - - + + + - - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - - - - + + + + - - - - - - - - - + + + + + + + + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - - - - - - + + + + + + - - + + - - - + + + - - - + + + - - + + - + - - - - - - + + + + + + - - - + + + - - - - - - - + + + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - + - + - + - + - + - - + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - + + - + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + @@ -96172,361 +97352,361 @@ - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - + + - - - + + + - + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - + + - + - + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - + - + - + - + - - + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - + + @@ -96534,497 +97714,497 @@ - - + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - + - + - + - - + + - - + + - - + + - - + + - + - - - - - - - - - - - - - + - - - - + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - - + + @@ -97034,1072 +98214,1072 @@ - + - + - + - - - - - - + + + + + + - - - + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - + - + - - - + + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + + - + - - + + - - + + - - + + - - - + + + - + - - + + - + - + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - - - + + + + + - - + + - + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - + + - + - - - - + + + + - - + + - + - + - - + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - + - - + + - - + + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - + - - + + - + - - + + - - + + - + - - + + - - + + - - + + - + - - - - + + + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - + + - - + + @@ -98110,8 +99290,8 @@ - - + + @@ -98139,527 +99319,506 @@ - - - - - - + + + + + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - - - - - - - - + + + + + + + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - + + - - + + - + - + - + - + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - + - - - - + + + + - - + + - - + + - + - - - - + + + + - - - + + + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - + - - + + - - - - - + + + + + - + - + - - - - - - + + + + + + - - - - + + + + - + - - + + - + - - + + - - + + - - + + @@ -98667,614 +99826,614 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - + - - + + - - - + + + - - - + + + - - + + - + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - + + + - + - + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + @@ -99282,656 +100441,656 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - - - + + - - - - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + - + @@ -99957,16 +101116,16 @@ - + - + - + - + @@ -100017,10 +101176,10 @@ - + - + @@ -100031,12 +101190,12 @@ - + - + @@ -100051,19 +101210,19 @@ - + - + - + - + @@ -100072,30 +101231,30 @@ - + - + - + - + - + - + - + - + - + @@ -100125,28 +101284,28 @@ - + - + - + - + - + - + - + - + @@ -100161,7 +101320,7 @@ - + @@ -100187,86 +101346,86 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -100274,90 +101433,90 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -100377,7 +101536,7 @@ - + @@ -100397,7 +101556,7 @@ - + @@ -100420,244 +101579,244 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - + + + - - + + - - + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - + @@ -100667,62 +101826,62 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -100737,1629 +101896,1629 @@ - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - + - + - + - + - + - + - - - + + + - - + + - - + + - + - + - + - + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - + - + - + - + - + - + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - + - + - - - + + + - - + + - - + + - - - + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - + - + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - - + + - - - - - - - + + + + + + + - - + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + + - - + + - - - - - + + + + + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - - - - - - - + + + + + + + + + - - + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - - + + @@ -102368,47 +103527,47 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - - - + + + @@ -102418,145 +103577,145 @@ - - - + + + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -102567,336 +103726,336 @@ - - + + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - - - - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + - - + + + + + + + + + + @@ -102905,1759 +104064,1768 @@ - - - - - + + + + + - - + + - + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - + - + - + - + - + - - + + - + - + - + - + - - - + + + - - - - + + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - - - + + + - - - + + + - - - + + + - - + + - + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - - - + + + + - + - - + + - - + + - - - - - - - - - - - - - - - - - + + - - - - + - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - + - + + + + - + - + - - - - - + + - + + + + - + + + + - + - + - + - - - - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + - + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - + - - - + + + - + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -104666,1095 +105834,1095 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - + + + + - - + + - + - - - - - - - + + + + + + + - + - - - + + + - + - + - - + + - + - - + + - + - + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - + + - + - + - + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + @@ -105762,832 +106930,832 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - + - - + + - - + + - - - + + + - + - - + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + - + + + + - - - - + - + - + + + + - - - - + - + - + - - + + - - + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - + - - + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -106598,10 +107766,10 @@ - + - + @@ -106618,47 +107786,47 @@ - + - + - + - - - - - + + + + + - - + + - - + + - - + + - + - + - + - + @@ -106693,1479 +107861,1479 @@ - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - + - + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - + - - + + - - - - - - - + + + + + + + - - - + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - + + - - - - + + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - - + + + - - + + - - - - + + + + - + - + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - - + + - - - - + + + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - + + - - + + - + - - - + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - + + + - + - - + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - + - + - - + + - - - + + + - - - + + + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -108174,240 +109342,240 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - + - - - - - + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + + - - - + + + - - + + - - - + + + - - + + - + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - + - + - + - + - - + + @@ -108416,1244 +109584,1244 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - - - + + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - + - - + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - - + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - + + - + - + - - + + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -109665,275 +110833,275 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -109975,8 +111143,8 @@ - - + + @@ -109984,30 +111152,30 @@ - + - + - + - + - + - + - + - + - - + + @@ -110030,588 +111198,588 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + - + - - + + - + - - + + - + - + - - - - - - - - - - + - + + + + - + + + + - - - - - - - + - + - - + + - - + + + + + + + + - - - - - - - - - - + - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - - - - - - - - - - - - - - - + - + - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -110628,642 +111796,594 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - + - - - - + - - - - - - - + - - - - - - - - - - + - - - - - - - + - + + + + + + + + + + + + + + + + - + - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -111271,460 +112391,457 @@ - + - + - + - + - + - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -111732,9 +112849,9 @@ - + - + @@ -111752,82 +112869,82 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + @@ -111837,284 +112954,284 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - - - - - - - - - + + - + - - + + - - + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -112122,507 +113239,507 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + - + - - + + - - + + - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -112630,4421 +113747,4421 @@ - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - + - - - + + + - - - + + + - - + + - - + + - + - + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - + + + - - - - - - - - - - - - + + - - + + - - - + + - - + + - - - - - + + - - - - - - - - - - - - - - - - - - + + + - - - + + + + - - - - - + + + - - - - + + + + - - - - - - - - - - - - - + + + - - - - - - - - + + - - - - - - - - + + + - - - - + + + - - - - + + + - - - - - - + + + - - - - - - - - - + + + - - - - + + + - - - - + + + - - + + + - - - - - - - - + + + - - + + - - + + - - + + + + + - - - - + + + - - - + + + + + - - + + + + - - + + + + - - - + + + - - + + + + - - - + + - - - + + + - - + + + + - - - + + + + + - - - + + + - - - + + + + + - - + + + + + + + - - - + + + + + + - - - - + + + + + + + + - - - - + + + + + + - - - + + + + + + + - - + + + + + + - - + + + + - - - + + + + - - - + + + + + - - + + + + + + + - - - + + - - - + + + - - - + + + + - - - + + + - - - + + + + + - - - - + + + + - - - + + + + + + - - - + + + - - - + + + - - + + + - - - + + + - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - + + + + + + - + - - - - - - - - - - - - - + - + - + - + - - + + - - + + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - + + - - + + - + - - - + + + - - - + + + - + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - + + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - + + - - + + - - - + + + - - - - - - - + + + + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - - - - + - + + + + + + + - + - + - - + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - + + - + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - + - + - + - + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - + - - - - - - + + + + + + - + - - - - - + + + + + - + - - - - + + + + - - - + + + - - + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - + + + + + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - + - + - + - - - + + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - - + + - - + + - - + + - - + + - + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + + - - + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - + - + - + - + - + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - + - + - + - + - - - - - + + + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - + - - - - - - + + + + + + - - + + @@ -117053,83 +118170,83 @@ - - - - - + + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - + + - - - - + + + + - - + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + @@ -117144,288 +118261,288 @@ - + - - - - - - - + + + + + + + - - + + - - + + - - - - - - + + + + + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - - - + + + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -117435,22 +118552,22 @@ - - + + - - + + - - + + @@ -117462,8 +118579,8 @@ - - + + @@ -117473,57 +118590,57 @@ - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - - + + @@ -117534,162 +118651,162 @@ - - - - - - - - + + + + + + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - + + - + - - + + - + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -117697,821 +118814,821 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - + - + - + - - - - - - - + + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - + + - - - + + + - - - - + + + + - + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - + - - + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - + + + + + - - + + - - - + + + - + - - + + - - + + - - - - + + + + - - + + - - + + - + - - + + - - - + + + - + @@ -118534,2046 +119651,2035 @@ - + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - + - - + + - - - - - + + + + + - + - - - + + + - + - + - + - + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - + - + - + - + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - + + - - - - - - + + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - + - + - + - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - + - + - - - - - - - + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - + - - - - + + + + - - - - + + + + - + - + - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - + - - - - - + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - + + + + - + - - + + - - + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + + - - + + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - + - - + + - - - - + + + + - - - + + + - - + + - + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - + - + - - + + - + - + - + - + - - + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - + - + - - + + - - - + + + - - - + + + - - + + - + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - + + - + - + - + - + - + - - + + - + - - + + - - + + - + - + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - - + + + - - + + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + @@ -120581,2761 +121687,2802 @@ - - + + - + - - - - - - + + + + + + - - - - - - - + + + + + + + - + - + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - - - - + + + + - + - - + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - - - - - - - - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + - + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - - + + - - - - + + + + - - + + - - - - + + + + - + - - + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - + + - - - - - + + + + + - - + + - - - - + + + + - + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + + + + + + + + + + - + + + + - + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - - - - - + + - - - - - - - - - - - - - - - - - - - + - - - - + - + - - - - + - + - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - + - - + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - + - - - + + + - - - - - - - + + + + + + + - - + + - - - + + + - + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - + + - - - - - + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - - + + + - - + + - - - - - - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + - + + + + + + + + + + - + - + - + - - + + - + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - - + + - - + + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + - - - - + + + + - + - + - + - + - + - - + + - + - + - + - + - + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - - + + - + - - - - - - - - - - - - - - - - - - - + - - - - + - - - - + - - - - + - - - - - - - - - - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -123346,57 +124493,57 @@ - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + @@ -123404,1397 +124551,1397 @@ - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - + - + - + - + - - + + - - - + + + - - + + - + - - + + - - + + - - + + - - - - - - - - + + + + + + + + - - - - + + + + - + - + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - - + + - + - - - - - - - - - - + + + + + + + + + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - + - - + + - + - + - + - - - - - + + + + + - - + + - + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - - + + - - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - + + - + - - - - - - + + + + + + - - + + - - - - - + + + + + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - + + - - + + - + - - + + - - + + - - + + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - - - + + + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - + - + - + - + - - - - - - - - - - + - - - - - - - - - - - - - - - - + - + - + - + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - + - + - + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -124803,55 +125950,55 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -124860,282 +126007,282 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -125144,389 +126291,389 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + @@ -125535,25 +126682,25 @@ - + - + - + - + - - + + - + - - + + @@ -125564,640 +126711,640 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - + + + - - - + + + - + - + - + - + - + - - - - + + + + - - + + - + - + - + - + - + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + @@ -126210,724 +127357,724 @@ - - + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - + - - + + - - - - + + + + - + - + - + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - + + - + - - + + - - - - + + + + - - + + - - - + + + - + - - - - - + + + + + - - + + - - - - - + + + + + - + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + @@ -126936,105 +128083,105 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -127048,154 +128195,157 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - - + + - + - + - + - + - + - + - + - + - - + + @@ -127210,544 +128360,547 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - - - - - - - - + + - + - - + + - - + + - - + + + + + + + + + + + - - + + - + - + - + - + - - + + - - + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -127758,8 +128911,8 @@ - - + + @@ -127772,8 +128925,8 @@ - - + + @@ -127799,8 +128952,8 @@ - - + + @@ -127813,455 +128966,480 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + + + + + + - - - - + + + + - - + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - + + + - - - - - - + + + - - - - - - + + + + - - - + + + + + - - - - + + + + + + - - - + + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + - - - - - - - - - + + + - - - + + + + - - - + + + - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + + - - - + + + - - - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + - - - - + + + + - - - - + + + + - + - - + + - + - - - - + + + + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - + - + @@ -128276,933 +129454,949 @@ - - - - - - + - + - + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - + + + + + - - - + + + - - + + - - - + + + - - - - - - - - - - - + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - + - + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - - - + + + + - - + + - - + + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - + - - - + + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - + - + - - + + @@ -129210,9 +130404,9 @@ - - - + + + @@ -129239,301 +130433,301 @@ - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + @@ -129561,219 +130755,219 @@ - - + + - - + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - - - - - - + + + + + + - - - + + + - - - + + + - + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - + - - + + @@ -129781,479 +130975,479 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -130264,13 +131458,13 @@ - + - + - + @@ -130279,225 +131473,225 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - + + + - - - - - - + + + + + + - - + + - + - - - - + + + + - - - + + + - + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -130523,451 +131717,223 @@ - + - - - - - - - - - + + + + + + + + + - - + + - - + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - - - - + + + + - - - - - + + + + + - - - - + + + + - + - + - + - + - - - + + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + + + + + + + - - - - - - - - - - - - - - - - - - + - + - - - - + - + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + - + - + - + @@ -130976,542 +131942,318 @@ - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - + - + - - - - - - - - - - - - - - - - - + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + @@ -131540,39 +132282,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -131586,7 +132328,7 @@ - + @@ -131598,7 +132340,7 @@ - + @@ -131612,10 +132354,10 @@ - + - + @@ -131623,13 +132365,13 @@ - + - + - + @@ -131655,28 +132397,28 @@ - - + + - + - + - + - + - + - + @@ -131700,206 +132442,218 @@ - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + - + - + - + + + + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -131910,8 +132664,8 @@ - - + + @@ -131920,74 +132674,86 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + @@ -131995,7 +132761,7 @@ - + @@ -132010,13 +132776,13 @@ - + - + - + @@ -132031,27 +132797,39 @@ - + - + - + - + - + - + - + + + + + + + + + + + + + - + @@ -132059,13 +132837,13 @@ - + - + @@ -132076,10 +132854,10 @@ - + - + @@ -132093,7 +132871,7 @@ - + @@ -132102,10 +132880,10 @@ - + - + @@ -132119,19 +132897,19 @@ - + - + - + - + - + @@ -132148,7 +132926,7 @@ - + @@ -132159,30 +132937,30 @@ - + - + - + - + - + - + - + - + - + @@ -132190,7 +132968,7 @@ - + @@ -132208,1370 +132986,1424 @@ - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + - - - - - - - - - - - - + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + - + + + + - + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - + - - + + - - + + - - + + - - + + - + - - - - + + + + - - - - - + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - - - - - - - + + - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - - + + - - + + - - - - + - + - + - + - + - + - + - + + + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -133587,227 +134419,227 @@ - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + @@ -133818,7 +134650,7 @@ - + @@ -133827,1324 +134659,1370 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - - + + + - - + + - - + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - + - - + + - + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - - - - + + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + + + + + - - - - + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - - + + + + - - - + + + - - - - - - - - - + + + + + + + + + - - + + - - + + - - - - - - + + + + + + - + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - + - + - + - + - - - + + + - - - + + + - + - - - - + + + + - - + + - + - - - - + + + + - - - - + + + + - - - + + + - + - - - + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + @@ -135153,148 +136031,148 @@ - - + + - - + + - + - + - - + + - + - + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -135302,63 +136180,63 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -135366,219 +136244,219 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -135587,1004 +136465,1571 @@ - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - + - - + + - + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + @@ -136596,184 +138041,184 @@ - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - + + - + - + - + - - - - + - + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - - + + @@ -136787,223 +138232,223 @@ - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - + + + + - - + + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - + - - - - - + + + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -137015,359 +138460,359 @@ - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -137376,15 +138821,15 @@ - + - + - + @@ -137395,1025 +138840,1453 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - + + - + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + + + + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -138425,58 +140298,58 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + @@ -138490,699 +140363,664 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - - - + + - - - - + - + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - + - + - + - + - + - + - - - + + + - - + + - - + + - + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + - - + + - - + + - + - - + + - - + + - + - + @@ -139191,315 +141029,315 @@ - - + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - + + + + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - + - - + + - + - + - + @@ -139508,364 +141346,364 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -139874,594 +141712,598 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - - + + - - - - + + + + - - - - - - + + + + + + - + - - + + - + - + - + - - + + - + - - + + - + - + - - + + - - + + - - + + - - + + - + - + - - + + - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - + - + - - - - + - + + + + - - - - - - - - - - + - + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -140470,381 +142312,381 @@ - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -140859,7 +142701,7 @@ - + @@ -140870,50 +142712,50 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -140942,7 +142784,7 @@ - + @@ -140951,7 +142793,7 @@ - + @@ -140959,7 +142801,7 @@ - + @@ -140976,7 +142818,7 @@ - + @@ -140985,7 +142827,7 @@ - + @@ -140994,10 +142836,10 @@ - + - + @@ -141005,10 +142847,10 @@ - + - + @@ -141016,9 +142858,9 @@ - + - + @@ -141027,24 +142869,24 @@ - + - + - + - + - + @@ -141053,15 +142895,15 @@ - + - + - + - + @@ -141075,7 +142917,7 @@ - + @@ -141087,12 +142929,12 @@ - + - + - + @@ -141101,7 +142943,7 @@ - + @@ -141109,10 +142951,10 @@ - + - + @@ -141120,7 +142962,7 @@ - + @@ -141134,10 +142976,10 @@ - + - + @@ -141154,10 +142996,10 @@ - + - + @@ -141166,7 +143008,7 @@ - + @@ -141175,10 +143017,10 @@ - + - + @@ -141198,24 +143040,24 @@ - + - + - + - + - + - + @@ -141223,35 +143065,35 @@ - + - + - + - + - + - + - + - + @@ -141265,13 +143107,13 @@ - + - + - + @@ -141282,16 +143124,16 @@ - + - + - + @@ -141299,13 +143141,13 @@ - + - + - + @@ -141331,8 +143173,8 @@ - - + + @@ -141349,12 +143191,12 @@ - + - + @@ -141366,7 +143208,7 @@ - + @@ -141378,12 +143220,12 @@ - + - + @@ -141395,7 +143237,7 @@ - + @@ -141404,7 +143246,7 @@ - + @@ -141412,19 +143254,19 @@ - + - + - + - + - + @@ -141433,7 +143275,7 @@ - + @@ -141444,16 +143286,16 @@ - + - + - + @@ -141468,23 +143310,23 @@ - + - + - + - + - + - + @@ -141493,21 +143335,21 @@ - + - + - + - + - + @@ -141515,36 +143357,36 @@ - + - + - + - + - + - + - + - + - + - + @@ -141552,26 +143394,26 @@ - + - + - + - + - + - + @@ -141583,12 +143425,12 @@ - + - + @@ -141600,12 +143442,12 @@ - + - + @@ -141626,7 +143468,7 @@ - + @@ -141634,7 +143476,7 @@ - + @@ -141645,36 +143487,36 @@ - + - + - + - + - + - + - + - + - + - + @@ -141682,13 +143524,13 @@ - + - + - + @@ -141705,7 +143547,7 @@ - + @@ -141713,20 +143555,20 @@ - + - + - + - + - + - + @@ -141734,58 +143576,58 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -141793,7 +143635,7 @@ - + @@ -141802,10 +143644,10 @@ - + - + @@ -141813,7 +143655,7 @@ - + @@ -141822,15 +143664,15 @@ - + - + - + @@ -141851,16 +143693,16 @@ - + - + - + - + @@ -141871,10 +143713,10 @@ - + - + @@ -141897,15 +143739,15 @@ - + - + - + - + @@ -141914,7 +143756,7 @@ - + @@ -141937,10 +143779,10 @@ - + - + @@ -141951,21 +143793,21 @@ - + - + - + - + - + @@ -141973,7 +143815,7 @@ - + @@ -141993,7 +143835,7 @@ - + @@ -142010,48 +143852,48 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -142101,7 +143943,7 @@ - + @@ -142110,10 +143952,10 @@ - + - + @@ -142124,10 +143966,10 @@ - + - + @@ -142138,18 +143980,18 @@ - + - + - + - + - + @@ -142175,10 +144017,10 @@ - + - + @@ -142189,13 +144031,13 @@ - + - + - + @@ -142206,157 +144048,157 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -142365,44 +144207,44 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -142416,147 +144258,147 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -142573,19 +144415,19 @@ - + - + - + - + - + @@ -142599,10 +144441,10 @@ - + - + @@ -142628,10 +144470,10 @@ - + - + @@ -142648,16 +144490,16 @@ - + - + - + @@ -142665,13 +144507,13 @@ - + - + - + @@ -142685,1412 +144527,1414 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - - + + + + - + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - + + + + + - - + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + - - - - + + + + + - - - - + + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + - - - - - + + + + + - - - - - - - - - - + + + + + - - - - + + + + - - + + + + - - + + + + - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - + - + - + - + - + - + - + - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -144104,27 +145948,27 @@ - + - + - + - + - + - + @@ -144133,12 +145977,12 @@ - + - + @@ -144168,10 +146012,10 @@ - + - + @@ -144185,19 +146029,19 @@ - + - + - + - + - + @@ -144226,7 +146070,7 @@ - + @@ -144264,25 +146108,25 @@ - + - + - + - + - + - + @@ -144302,30 +146146,30 @@ - + - + - + - + - + - + - + - + - + @@ -144336,7 +146180,7 @@ - + @@ -144351,25 +146195,25 @@ - + - + - + - + - + - + - + @@ -144381,19 +146225,19 @@ - + - + - + - + @@ -144405,101 +146249,101 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -144532,7 +146376,7 @@ - + @@ -144547,12 +146391,12 @@ - + - + - + @@ -144564,12 +146408,12 @@ - + - + - + @@ -144578,53 +146422,53 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -144638,8 +146482,8 @@ - - + + @@ -144654,284 +146498,284 @@ - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -144940,260 +146784,277 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + - + @@ -145202,41 +147063,41 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -145244,43 +147105,43 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -145291,1267 +147152,1268 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - + + + + - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - + + - - + + - - + + - - - + + + - + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - + - - - - - + + + + + - + - - - + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - - - + + + - - - - - - - - - + + + + + + + + + - - + + - + - + - + - - + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - + - - - + + + - - - + + + - - - - - - - + + + + + + + - - + + - - + + - - - - + + + + - - - - - - + + + + + + - + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -146565,8 +148427,8 @@ - - + + @@ -146578,8 +148440,8 @@ - - + + @@ -146652,310 +148514,310 @@ - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - + - + - + - + - + + + + + + + - + + + + + + + + + + - + + + + + + + + + + + + + + + + - + + + + - + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -146965,677 +148827,921 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + - + - + - + - + - + + + + + + + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - + - - - + + + - - - - + + + + - - - + + + - - + + - + - + - + - + - - + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - + - - + + - - + + - + - - + + - - - + + + - - + + - + - + - + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - + + + - + - - + + - - - + + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - + - - - + + + - - - + + + - - - + + + - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - + - - + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + @@ -147644,2283 +149750,2298 @@ - + - + - + - + - + - - + + - - - - - + + - + - - + + - + + + + - + - - - - + - - + + - - + + - - + + - - + + - - + + - + + + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - + + + + + + - + - + - + - - - - + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - - + + - + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - - + + + + - + - - + + - - + + - - + + - - - + + + - - + + - + - - - + + + - - + + - - + + - - + + - - + + - + - + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + - - - - - + + + + + - - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - + - + - - - + + + - - + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - + - + - - + + - - + + - + - - + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - - - + + + + + - + - - + + - - - - - + + + + + - - - - + + + + - - + + - - + + - + - + - + - + - - - + + + - - + + - - + + - - + + - + - + - - - + + + - - + + - - - - - - - + + + + + + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - + - + - + - - + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - - - + + + + + + + - - + + - - + + - - + + - - - + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - + + - - + + - - + + - - + + - + - - + + - + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - - + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - + + - + - + - + - + - - + + - - + + - + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + + - - - + + + - - + + - - + + - - - - - - - + + + + + + + - + - + - - + + - - + + - + - - - - - + + + + + - - + + - - + + - + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - + - + - + - - - - + - + - + - - - - + - + - + - + - + - + - + - + + + + - - - - + - - - - + - + + + + + + + + + + - + + + + + + + - + + + + + + + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + - - + + @@ -149932,92 +152053,92 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -150027,8 +152148,8 @@ - - + + @@ -150052,8 +152173,8 @@ - - + + @@ -150065,438 +152186,438 @@ - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + - - + + - + - - - + + + - + - - + + - + - + - - + + - + - + - + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + - + - + - + - + + + + + + + + + + - + - + - - + + - - + + - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - + - - - - - + + + + + - - - + + + - - + + - + - - + + - + - + - + - + - + - - - + + + - + - + - + - + - + - - - - - - - - - - - - - + - + - + - + - + + + + + + + + + + - + - + - - + + + + + - + @@ -150504,919 +152625,919 @@ - - + + - - + + - - + + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - + - - + + - - + + - - - + + + - + - + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - + - - + + - - - - + + + + - + - - - - - + + + + + - - + + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - - - + + + - - - + + + - - + + - - - - + + + + - - + + - - - + + + - - + + - - + + - + - - - + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - + - + - + - + - + - + - + - - + + - - - - - + + + + + - + - - + + - - + + - + - - - + + + - + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - + - - + + - - + + - + - - + + - - + + - - + + - - + + @@ -151424,4239 +153545,4247 @@ - - + + - - - - + + + + - - + + - - - + + + - + - + - - + + - + - - - + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - + - - - - + - + - + - - - - + - + - + - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + + + + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + - - - - + - + + + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + - - - - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - - - - - - - + + + + + + + - - + + - + - - + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - - - - - - - + + + + + + + + + - - + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + - + - - + + + + + + + + - + - + - + - - - - - - - + - - - - - - - - - - + - + - - + + - - + + + + + + + + + + + + + + - + - + - - + + - - + + + + + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + + + + + + + + + - - - + + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + - + - + - - - - - - - - - - + - + - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + - - - - + - + - - + + - + - - + + - - - - - + + - + + + + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - + + + + - + + + + + + + + + + + + + + + + - - - - + - - - - - - - - - - - - - - - - + - + + + + - + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - + - - - + + + - - - - + + + + - - - - + + + + - + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - + + + + + + + - + - + - + - + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - - - + + + - + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - + - + - + - - - - - + + + + + - - - + + + - - - - - - - + + + + + + + - - - - - + + + + + - + - - + + - + - + - + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - - - + + + - - + + - - - - - - + + + + + + - - + + - + - - + + - - - - - - - - + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - + + + - + - + - - - - + + + + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - + + + + - - + + - - - + + + - + - - - + + + - - - + + + - + - - + + - - + + - - - + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - + + + - + - - - + + + - + - - - + + + - - - + + + - + - - - - + + + + - + - + - + - + - + - + - + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - - - - - + + + + + - - + + - + - - - - + + + + - - - - + + + + - - - - + + + + - + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - + + - + - - - + + + - - + + - + - + - - + + - - - - - + + + + + - - - + + + - - - + + + - + - + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - + - + - + - + - + - - - - - + + + + + - - - - + + + + - - + + - - + + - + - + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - + - - + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - + - + @@ -155665,192 +157794,192 @@ - + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - + + - + - + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - + + @@ -155858,13 +157987,13 @@ - - + + - - + + @@ -155891,1185 +158020,1951 @@ - - + + - - + + - - - - - - + + + + + + - - + + - + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - + + - - - - - + + + + + - - + + - - + + - - - - + + + + - - + + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - + - - + + - + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - + + - + - - + + - - + + - - + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - - - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - - - - - - - - + + + - - - - + + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - + - + - - - - - - - - - - + - + + + + - + + + + + + + + + + + + + + + + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + + + + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -157106,54 +160001,54 @@ - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + @@ -157161,93 +160056,93 @@ - - + + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -157255,528 +160150,528 @@ - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - + - - - - - - - + + + + + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - + - + - + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - + - - + + - - + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - - + + @@ -157784,815 +160679,815 @@ - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - - + + + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - - - + + + + + + + + + - - - - - + + + + + - - - + + + - + - + - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - + - + + + + - + - + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -158601,1174 +161496,1174 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - - - - - - - + + + + + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - + - + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - - - + + + + - - + + - + - + - - + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - + - - + + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -159777,362 +162672,362 @@ - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + - + - + - - + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -160148,695 +163043,695 @@ - - + + - - + + - + - - - + + + - - + + - - - - + + + + - - - + + + - + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - + + + - + - - + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - + + - - - - - - + + + + + + - + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - + - - - - - + + + + + - - - + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - + + + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - - + + + + - + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - + + - - - - - + + + + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - + @@ -160848,1366 +163743,1366 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - - - - - - - + + + + + + + + + - + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - + - - - - - - - - - + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - - - - - - - + + + + + + + + + + - - + + - - + + - - + + - - - - + + + + - - + + - + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - + @@ -162239,7 +165134,7 @@ - + @@ -162253,13 +165148,13 @@ - + - + - + @@ -162268,312 +165163,312 @@ - + - - + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -162585,488 +165480,488 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -163107,261 +166002,261 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + @@ -163373,154 +166268,154 @@ - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + @@ -163528,7 +166423,7 @@ - + @@ -163563,61 +166458,61 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -163632,7 +166527,7 @@ - + @@ -163643,7 +166538,7 @@ - + @@ -163651,40 +166546,40 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -163707,7 +166602,7 @@ - + @@ -163722,12 +166617,12 @@ - + - + - + @@ -163742,10 +166637,10 @@ - + - + @@ -163754,7 +166649,7 @@ - + @@ -163777,7 +166672,7 @@ - + @@ -163788,25 +166683,25 @@ - + - + - + - + - + @@ -163823,15 +166718,15 @@ - + - + - + - + @@ -163851,13 +166746,13 @@ - + - + - + @@ -163865,21 +166760,21 @@ - + - + - + - + @@ -163900,586 +166795,586 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -164500,1862 +167395,1862 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - + + - + - + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + + - - - - - + + + + - - - - + + + + - - - - - + + + + + + + - - - - + + + + + + + - - - - - + + + + + + - - - - + + + + + + + - - - - + + + + + + - - - - - + + + + + - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + - - - - + + + + + - - - + + + + - - - - + + + + + - - - - - + + + - - - + + + + - - - - + + + + + - - - - + + + + + + + - - - - + + + + + + - - - - - - - + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + - - - - - + + + - - - - - - + + + + + - - - - - + + + + - - - - - + + + - - - - - + + + + - - - - + + + + - - - - - + + + + - - - - + + + + + - - - - - + + + + - - - + + + + - - - - + + + - - - - - + + + + - - - - - - - + + + + - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - + - + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - - + + - - - - + + + + - + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - + + - - - - - + + + + + - - - + + + - + - + - + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - - - - + + + + + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + @@ -166364,15 +169259,15 @@ - + - + - + - + @@ -166381,7 +169276,7 @@ - + @@ -166395,35 +169290,35 @@ - + - + - + - + - + - + - + - + - + @@ -166440,529 +169335,533 @@ - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - + - - + + - + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - + - - - + + + - - + + + + + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -166970,234 +169869,431 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - + + + + + + + - - - - + - + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + @@ -167209,13 +170305,13 @@ - + - + - + @@ -167223,35 +170319,35 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -167260,48 +170356,48 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -167327,60 +170423,60 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -167391,9 +170487,9 @@ - + - + @@ -167411,27 +170507,27 @@ - + - + - + - + - + - + - + - + @@ -167442,7 +170538,7 @@ - + @@ -167456,84 +170552,84 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -167541,7 +170637,7 @@ - + @@ -167550,828 +170646,934 @@ - + - + + + + + + - + + + + + + + + + + - + + + + - + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + - + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - + - - - + + + - + - + - - + + - - - - + + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - - - + + + - - + + - + @@ -168379,467 +171581,662 @@ - - + + - - + + - + - + - + - + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - + - + - - + + - - - - - + + + + + - - - - - + + + + + - - + + - + + + + + - + - + + + + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - - + + - + - + - - + + @@ -168852,344 +172249,348 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + - + - - - - - - - - - - + + + + + + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -169204,725 +172605,693 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - + - - + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - - + + + - + - - + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - + + - - + + - + - - - + + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - - - - + + + + - + - + - + - - + + - - - + + + - - - + + + - + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - - - - - - + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -169951,81 +173320,81 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -170033,917 +173402,944 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - + + + - + - + - + - + - - - + + + - + - - - - - - - + + + + + + + - - - - - + + + + + - + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - + - - + + - - - + + + - + - - + + - - + + - + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - + - + - - - + + + - + - + - - - - - + + + + + - - - + + + - - + + - + - - - - - - - + + + + + + + - - - + + + - - + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - + - - - - + + + + - + - - - + + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - - + + + + + + + + - - + + - + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - - + + + + - - + + - + - + - + - + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - - - + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + @@ -170955,341 +174351,341 @@ - + - + - + - + - + - + - + - - - - - + + + + + - - - - + + + + - - + + - + - + - + - + - + - - + + - - - + + + - - - + + + - - + + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - + - - + + - - + + - - + + - + - + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - + - - + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - + + + - - + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - + + + + - - + - - + + - + - + @@ -171298,103 +174694,103 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -171418,27 +174814,27 @@ - + - + - + - - + + - + - + - + - + @@ -171452,999 +174848,991 @@ - + - + - + - + - + - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - - + + + + - - + + - - - + + + - - + + - - - + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - - - + + + + + - - - + + + - + - - + + - - - - + + + + - - + + - + - - + + - - - - - + + + + + - - + + - - - - + + + + - - + + - + - - + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - + - + - - - + + + - + - + - + - + - + - + - + - + - + @@ -172459,134 +175847,153 @@ - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - - + + - - - - - + + + + + - + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - + - - - + + + - + - - - - + + + + - + - + @@ -172595,358 +176002,358 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - - + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -172956,33 +176363,33 @@ - + - + - + - + - + - + - + - + - - + + @@ -172990,909 +176397,909 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - - + + + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - + - + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - + - + - - + + - - - - - - - - - + + + + + + + + + - - - - + + + + - + - + - + - + - + - - - - + + + + - - - - - - - - + + + + + + + + - + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - - - + + + + + - + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + - + - + - + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - - + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + - + - - + + - - + + - + - + - + - - + + @@ -173926,49 +177333,49 @@ - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + @@ -173984,17 +177391,17 @@ - - + + - + - + - - + + @@ -174003,43 +177410,43 @@ - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + @@ -174052,23 +177459,23 @@ - - + + - + - + - + - + - - + + @@ -174094,38 +177501,38 @@ - - + + - + - + - - + + - + - + - - + + - + - + - + - - + + @@ -174147,26 +177554,26 @@ - - + + - + - + - - + + - + - + - - + + @@ -174181,29 +177588,29 @@ - - + + - + - + - - + + - + - + - + - - + + @@ -174230,17 +177637,17 @@ - - + + - + - + - - + + @@ -174265,17 +177672,17 @@ - - + + - + - + - - + + @@ -174291,20 +177698,20 @@ - - + + - + - + - + - - + + @@ -174322,20 +177729,20 @@ - - + + - + - + - + - - + + @@ -174348,25 +177755,25 @@ - - + + - + - + - + - + - + - - + + @@ -174395,33 +177802,33 @@ - - + + - + - + - - + + - - + + - + - + - + - - + + @@ -174433,17 +177840,17 @@ - - + + - + - + - - + + @@ -174458,46 +177865,46 @@ - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + @@ -174531,65 +177938,65 @@ - - + + - + - + - - + + - + - + - + - + - - + + - - + + - + - + - + - - + + - - + + - + - + - - + + @@ -174600,31 +178007,31 @@ - + - + - - + + - + - + - - + + - + - + - - + + @@ -174640,19 +178047,19 @@ - + - + - - + + - + - - + + @@ -174668,42 +178075,42 @@ - - + + - + - + - - + + - + - + - - + + - + - + - + - - + + @@ -174718,36 +178125,36 @@ - - + + - + - + - - + + - + - + - - + + - + - + - - + + @@ -174756,116 +178163,116 @@ - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - - + + - + - + - - + + - + - + - - + + - + - + - + - - + + @@ -174877,29 +178284,29 @@ - - + + - + - + - - + + - + - + - + - - + + @@ -174917,29 +178324,29 @@ - - + + - + - + - - + + - + - + - + - - + + @@ -174956,35 +178363,35 @@ - - + + - + - + - - + + - + - + - + - + - + - - + + @@ -175005,14 +178412,14 @@ - - + + - + - - + + @@ -175025,29 +178432,29 @@ - - + + - + - + - - + + - + - + - + - - + + @@ -175057,59 +178464,59 @@ - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - - + + @@ -175126,22 +178533,22 @@ - + - + - - + + - + - + - - + + @@ -175167,99 +178574,99 @@ - + - + - - + + - + - + - + - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - - + + @@ -175268,1612 +178675,1501 @@ - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - - + + + + + - - - - + + + + - - + + - + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - - + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - - - - + + + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - + - + - + - + - - + + - - + + - - - - - - - - + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - - + + - - - - + + + + - - - - + + + + - + - - - - + + + + - - - - - + + + + + - + - - + + - + - + - - + + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - + + + - - + + - + - + - + - + - + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - + - + - + - + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - + - + - + - + - - + + - - - + + + - - - - - + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - + - - + + - - + + - - - - + + + + - - + + - + - - + + - - - + + + - - + + - - - - + + + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - + + + - + - + - + - - - + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - + + + + - + - + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + @@ -176882,26 +180178,26 @@ - + - + - + - + - + - + - + @@ -176910,307 +180206,307 @@ - + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - + + - + - - + + - + - + - + - - - - + + + + - - - + + + - + - + - + - + @@ -177219,590 +180515,590 @@ - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - + - - + + - + - - + + - + - + - - + + - - + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + - + - - - - + - + - + - + - + - + + + + + + + + + + - + + + + - + - + - + - + - + - + - + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + + + + - - - - - - - - - - + - + + + + - + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + - - - - - - - - - - + - + - + - + - + - - + + - - + + - + - + - + - + - + + + + + + + - + - + - + - + - - - - - - - - - - - + + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - + + - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - + - - - - + - + + + + + + + + + + - + + + + + + + - + + + + - + + + + - + + + + - + + + + - + + + + + + + + + + + + + + + + + + + - + - + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -177810,78 +181106,78 @@ - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + @@ -177905,7 +181201,7 @@ - + @@ -177914,100 +181210,100 @@ - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -178016,7 +181312,7 @@ - + @@ -178025,206 +181321,206 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -178232,7 +181528,7 @@ - + @@ -178246,140 +181542,140 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -178396,3189 +181692,3243 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - - - - + + + + + + + - - + + - + - + - - + + - + - - - - - - - - + + + + + + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - + - + - + - + - + - + - - + + - - - - - + + + + + - - + + - - - - - + + + + + - - + + - - + + - - + + - - - + + + - - + + - + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - + - + - + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - - - + + + + - + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - + + - - - + + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - - - - + + + + + - - - + + + - + - + - - - + + + - - + + - - + + - - - + + + - - + + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - - - - - + + + + + + - - - + + + - - + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - + - - + + - - + + - - - - + + + + - + - - - + + + - - - + + + - + - + - - - - + + + + - + - + - + - - - - - - + + + + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - - + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - + - - - - - - - - - - + + + + + + + + + + - - - + + + - + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - - - - - - - - - - - - - - - + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - - - - - - - - + - + + + + + + + - + - + - - - - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - - - - - - + + + + + + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - + - - - + + + - - - + + + - - - - - + + + + + - + - + - + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - + + + + + + + + + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - - + + - - - - - + + + + + - - + + - - - - - - - - + + + + + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - + - - - - - + + + + + - + - - + + - - + + - + - - + + - + - + - - - + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - + + - - - - + + + + - - - + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - + + + + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - + - - - - + + + + - - - + + + - - - + + + - - - - - - + + + + + + - + - + - + - + - + + + + + + @@ -181586,65 +184936,65 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -181652,122 +185002,118 @@ - + - + - + - - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - - - - - - - + + + + + + + - + - - - + + + - - - - - - + + + + + + - - - - - + - + - + - + - + @@ -181775,395 +185121,395 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - - - - + + + + + - - + + - - - - - - - - + + + + + + + + - + - - + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - + + + - + - - - + + + - + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -182172,13 +185518,13 @@ - + - + - + @@ -182187,133 +185533,133 @@ - - - - - + + + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -182322,28 +185668,28 @@ - + - + - + - + - + - + - + - + @@ -182352,19 +185698,19 @@ - + - + - + - + @@ -182372,94 +185718,94 @@ - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + @@ -182476,21 +185822,21 @@ - + - + - + - + - + - + @@ -182499,21 +185845,7 @@ - - - - - - - - - - - - - - - + @@ -182527,7 +185859,7 @@ - + @@ -182545,7 +185877,7 @@ - + @@ -182712,563 +186044,574 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - - - - - + + + + + + + + + + - + - - + + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - + - + - - - + + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - - - + + + - - + + - - - - - + + + + + - - - - - - + - - + + - + - + - + - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - + - + - + - + - + - + - + - + @@ -183280,7 +186623,7 @@ - + @@ -183288,1008 +186631,1017 @@ - + - - + + - - + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - + + - - - - + + + + - - - + + + - - - + + + + + + + + + + + + + + + + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - - + + + - - + + - - + + - - + + - + - - + + - - - - + + + + - - - + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - + + + + - - + + - - + + - + - - + + - + - - - + + + - - + + - - - + + + - - + + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - - - + + + + + + + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + - - - - - - - - + - - - - - - - + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - - - + + + + - - + + - - + + - + - - - - + + + + - + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - + - + - - + + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + @@ -184304,13 +187656,13 @@ - + - + - + @@ -184322,255 +187674,255 @@ - + - + - + - - - - - - - - - - + - + + + + - + - - - - - - - + - + - + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - + - - - - - + + + + + - - + + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -184578,16 +187930,16 @@ - + - + - + - - + + @@ -184598,763 +187950,771 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - + - + - + - - + + - + - - + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - + + - - + + - - - - + + + + - + - - - - - + + + + + - - - + + + - - - - - + + + + + - + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - + + - + - + - - - - - - - + + + + + + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - + + + - + - + - - - + + + - - - - - - + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - + - - + + - + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - + - + - + - + - - + + - - - - + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - + + + + + + + + + @@ -185374,49 +188734,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -185425,741 +188785,719 @@ - + - + - + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - + - - + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - - - - - - - - - - - - - - + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - - + + + - + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - - - - + + + + + - + - - - - - - - + + + + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - + - - - + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - - - + + + + - - + + - - - - - - - - + + + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - + - + - - - - - - - - - - - - + @@ -186167,41 +189505,41 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -186218,7 +189556,7 @@ - + @@ -186238,194 +189576,194 @@ - + - + - - - - - - + + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - + - - - + + + - - + + - + - - - + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + @@ -186436,7 +189774,7 @@ - + @@ -186445,250 +189783,250 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - - - - - + + + + + + + - - - + + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - + - + - + - + - - + + - - - + + + - - - - - + + + + + - + - - - + + + - + - + - + - + - - + + - - - - - + + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -186697,13 +190035,13 @@ - + - + - + @@ -186715,116 +190053,89 @@ - - + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - + - - - - + + + + - + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -186836,31 +190147,31 @@ - + - + - + - + - + - + - + - + @@ -186875,107 +190186,118 @@ - + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - + - + - + - + - + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - + - - + + - - - - + + + + @@ -186983,243 +190305,243 @@ - - + + - - - + + + - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - - - + + + - - - - + + + + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - - + + - - - + + + - + - + - + - + @@ -187228,34 +190550,34 @@ - + - + - + - + - + - + - + - + - + @@ -187270,10 +190592,10 @@ - + - + @@ -187285,28 +190607,28 @@ - + - + - + - + - + - + @@ -187321,13 +190643,13 @@ - + - + - + @@ -187336,49 +190658,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -187387,16 +190709,16 @@ - + - + - + - + @@ -187411,37 +190733,37 @@ - + - + - + - + - + - + - + - + - + - + @@ -187462,10 +190784,10 @@ - + - + @@ -187474,67 +190796,67 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -187543,357 +190865,357 @@ - + - + - + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - + + - + - - - - - + + - + - - + + - - + + - - + + - - + + - - - - - + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - + + - + - - + + - - - - - + + - + + + + + + + - + + + + - + - - + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - + - - + + - - + + - + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + @@ -187925,19 +191247,43 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + @@ -187949,53 +191295,53 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -188007,7 +191353,7 @@ - + @@ -188016,13 +191362,13 @@ - + - + - + @@ -188052,58 +191398,58 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -188115,336 +191461,336 @@ - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - + - + - - + + - - + + - - - - - - + + + + + + - - + + - - + + - + - - + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - + - + - + - + @@ -188462,80 +191808,80 @@ - + - - + + - + - + - - - - + - - + + - - - - - - - + - - - - + - + - + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + @@ -188544,37 +191890,37 @@ - + - + - + - + - + - + - + - + - + @@ -188592,7 +191938,7 @@ - + @@ -188607,31 +191953,31 @@ - + - + - + - + - + - + - + - + @@ -188640,13 +191986,13 @@ - + - + - + @@ -188664,49 +192010,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -188715,7 +192061,7 @@ - + @@ -188733,7 +192079,7 @@ - + @@ -188745,140 +192091,140 @@ - + - - + + - - - - - - - - + + - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -188886,32 +192232,32 @@ - + - + - + - + - + - + - + - + - + - + @@ -188920,66 +192266,66 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + @@ -188994,1768 +192340,1751 @@ - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - - - + + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - + - - - - + + + + - + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - - + + + + + + + + - - + + - + - - + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - + + + - + - + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - - - + + + + + - + - - + + - - + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - - - - - + + + + + + - - - - + + + + - + - + - - - + + + - - + + - - + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - + - - - - + + + + - - - - - - - - + + + + + + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - + - + - + - + - + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - - + + + + + - + - + - + - + - + - + - + - - + + - - - + + + - - + + - - - - + + + + - + - - + + - - + + - + - - - - + + + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - + + - + - - + + - + - - + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - + + - + - + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - + - - + + - - - + + + - - + + - + - - + + - + - + - + - + - + - + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - + - + - - - - - - + + + + + + - - - - + + + + - - + + - + - - + + - + - - + + - + - - - - + + + + - - + + - - + + - - - + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - + - - - - - - + + + + + + - + - - - - + + + + - - - - + + + + - + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - + + - - + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + - + - + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - + - - - - + + + + - - + + - - - - + + + + - - + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -190764,116 +194093,116 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + @@ -190902,8 +194231,8 @@ - - + + @@ -190912,1201 +194241,1185 @@ - + - + - + - + - + - + - + - - - - - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - + + - - - + + + - - + + - + - - + + - - - + + + - - - - - - - - + + + + + + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - + + - - - - + + + + - - - + + + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - - - - - - - + - - - - + - - - - + - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - + - - - - + - + - - - - + - + - - - - - - - - - - - - - - - - + - + + + + - + - + - - - - + - + - + + + + - + - + - - - - + - + - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - - - - - + - + - - + + - - + + - - - - - - - - + + - + - + - - + + - + - + - + - - - - - - - + - - - - - - - + - - - - + - + - - - - + - - - - - - - - - - - - - + - - - - - - - + - - - - + - + - + - + - + - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - - - - - - - + - - - - + - + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -192117,103 +195430,103 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -192224,7 +195537,7 @@ - + @@ -192232,274 +195545,274 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + - - - - + - + - - + + - - + + - - - - - - - - - - - - - - + + - + + + + + + + - - - - + - + + + + - + + + + + + + - + - + + + + - + - - + + + + + - - + + @@ -192516,222 +195829,222 @@ - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -192741,16 +196054,16 @@ - + - + - + - - + + @@ -192764,391 +196077,391 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -193156,251 +196469,251 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -193413,160 +196726,160 @@ - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -193574,206 +196887,206 @@ - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -193781,603 +197094,603 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + @@ -194385,545 +197698,545 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + @@ -195069,8 +198382,8 @@ - - + + @@ -195078,1765 +198391,1764 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - + - - + + - - + + - + - - - + + + - + - + - + - + - - - - - + + + + + - - + + - - - + + + - - + + - + - + - + - - + + - - + + - + - + - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - + + + + - - - - - - + + + + - - - - - - + + + + - - - - - + + + + - - - - - - + + + + - - - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + - - - - - - - - + + + + + - - - - - - - + + + + + - - - - - - - - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - - - - + + + + + - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + - - - - - + + + + + + - - - - - - + + + + + + + - - - - - + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - + + + + + + + + - - - - - - - - + + + + + - - - - - + + + + + + - - - - - - + + + + - - - - + + + - - - + + + + - - - - + + + + + - - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + + - - - - - + + + + + + - - - - - - + + + + + - - - - - - - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - + + + - - - + + + - + - + - + - + - - - + + + - - + + - + - - + + - + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - - + + - - + + - + - - - - + + + + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - + + - - + + - + - - - + + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - + + + - - + + - - + + @@ -197123,1180 +200435,1180 @@ - + - + - + - + - + - + - - - + + + - - - - - - + + + + + + - - - + + + - + - + - - - - + + + + - - - + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - - + + + - + - + - - - + + + - - - + + + - - + + - + - - + + - - - - - + + + + + - + - + - - + + - + - + - - - + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - + - - - - - - + + + + + + - + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - + + - - + + - - - - - - - - - + + + + + + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - + + - - + + - - - - - - - - + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - - - - + + + + + + - - + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - - - - - - + + + + + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - - + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - + + - - + + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -198309,1429 +201621,1429 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + - + + + + - - - - - - - + - + - - + + - - + + + + + - + - - + + - - + + - - + + - + + + + + + + - - + + - - + + - - + + - - + + - - - - - - - - + + - + - - + + - - + + - - + + - + - + - - - - - + + - - - - + - - - - + - + - - + + + + + + + + + + + - - - - + - + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + - - - - - - - + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -199740,1968 +203052,1968 @@ - + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + - + - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + + + + + + + - + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + - - - - - - - - - - + - - - - - - - + - + - + + + + + + + + + + - + - - - - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + - + + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - - - - - - - - - - - - - - - - - - + - - - - + - + - - + + - - + + - - + + + + + + + + + + + + + + - + - - + + - - + + + + + - + - - + + - - + + - - + + + + + - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -201721,568 +205033,568 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -202290,2257 +205602,2257 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - - - - + + + + + + + - - + + - - + + - - + + - - - + + + - + - + - - + + - - + + - - - + + + - - - - - + + + + + - + - + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + - - - - - + + + + + + - - - - - - - + + + + + - - - - - - - - - + + + + + - - - - - + + + + + + - - - - - + + + + + - - - - - - + + + + + - - - - - - + + + + + + + - - - - - + + + + + - - - - + + + + + - - - - - + + + + + - - - - - + + + + + + + - - - + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + - - - - - - + + + + + + - - - - - + + + + + + - - - - - + + + + + - - - - - - - - + + + + - - - - - + + + + + - - - - - - + + + + + - - - - - - + + + - - - - - + + + + + - - - - - + + + + - - - - - + + + + - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - + - - - - - + + + + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - + + - + - - - + + + - - - + + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - + + - - - - - - + + + + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - + + - - - - - - + + + + + + - + - - + + - - + + - - - + + + - - + + - - + + - + - - - - - - - - - - - + + + + + + + + + + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - - + + - - - - + + + + - - - - - + + + + + - - + + - + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - + - - - + + + - + - - - + + + - + - + - + - + - + - + - - + + - - - - - + + + + + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - + - + - - + + - - - - - + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - + - + - + - + - + - + - + - + - - + + @@ -204551,927 +207863,927 @@ - - - - - + + + + + - - + + - - + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - - + + - + - + - - + + - + - - - + + + - + - + - - - - + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - + - - - - + + + + - - - + + + - - + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - + - + - - - + + + - - + + - - + + - + - + - - + + - - - - + + + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - + + - - - - - - + + + + + + - - + + - - + + - - + + - - - - + + + + - + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - - - - + + + + + + + - - - + + + - + - + - + - + - + - + - + - + - + - + - - - + + + - - - + + + - - - - - + + + + + - - + + - - + + - - + + - + - + - + - + - + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - - + + + + + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - + + - - - - - + + + + + - - + + - - + + @@ -205494,1276 +208806,1276 @@ - + - + - + - + - + - + - + - - + + - - - + + + - - + + - + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - - - + + + + - + - - + + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - + + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - - + + + + - + - - - + + + - - - - + + + + - - - + + + - + - - + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - + - - + + - - + + - - - + + + - + - + - + - + - + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - + + - + - + - - - + + + - - - + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - + - + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + @@ -206774,13 +210086,13 @@ - + - + - + @@ -206788,9 +210100,9 @@ - + - + @@ -206802,7 +210114,7 @@ - + @@ -206813,479 +210125,479 @@ - - + + - + - - + + - - - - - + + + + + - + - - + + - - + + - + - + - + - + - - - + + + - - - - - - - - - + + + + + + + + + - - - + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + - - + + - + - - - + + + - - + + - - + + - - - + + + - + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - + - + - - - - - + + + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - + + - + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - + - - - - + + + + - - + + - - - - + + + + - - + + - + - - - + + + - - - + + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - + - - - - + + + + - - - - + + + + - - - + + + - + - + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - + - + - + @@ -207299,521 +210611,521 @@ - - - - - + + + + + - - - - - + + + + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - + + + - + - + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - - - + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - + - - + + - - - - - - - + + + + + + + - - - - - + + + + + - - - + + + - - - + + + - - - - - - + + + + + + - - + + - - - + + + - - + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - - + + + + + + - + - - - - + + + + - - - - + + + + - - + + - - - - + + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + + + + + + + + + + - + - - - - - - - - - - - + + + + + + + + + + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + - + - + - + - + @@ -207830,95 +211142,95 @@ - - - - + + + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - + - - - - + + + + - - - - - + + + + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - + @@ -207926,198 +211238,198 @@ - - + + - - + + - - + + - - + + - + - + - - + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - + - + - + - - - + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - + + - - - + + + - + - - - - + + + + - + - - - + + + - - - - + + + + - - - + + + - + - - + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + diff --git a/abi_gki_aarch64_cuttlefish_whitelist b/abi_gki_aarch64_cuttlefish_whitelist index 832fba7fdbff..3c065d8bca85 100644 --- a/abi_gki_aarch64_cuttlefish_whitelist +++ b/abi_gki_aarch64_cuttlefish_whitelist @@ -8,8 +8,7 @@ __arch_copy_from_user __arch_copy_to_user arm64_const_caps_ready - bus_register - bus_unregister + bcmp cancel_delayed_work_sync capable __cfi_slowpath @@ -18,15 +17,10 @@ consume_skb cpu_hwcap_keys cpu_hwcaps - cpumask_next cpu_number __cpu_online_mask - cpus_read_lock - cpus_read_unlock - debug_smp_processor_id delayed_work_timer_fn destroy_workqueue - dev_driver_string _dev_err device_register device_unregister @@ -36,15 +30,12 @@ dev_queue_xmit dev_set_name _dev_warn - dma_alloc_attrs - dma_direct_map_page - dma_direct_unmap_page dma_fence_release dma_fence_wait_timeout - dma_free_attrs dma_resv_add_excl_fence dma_set_coherent_mask dma_set_mask + down_write ethtool_op_get_link eth_validate_addr event_triggers_call @@ -55,11 +46,13 @@ free_irq free_netdev __free_pages + get_device get_random_bytes get_unused_fd_flags + hwrng_register + hwrng_unregister ida_alloc_range ida_free - init_net init_timer_key init_wait_entry __init_waitqueue_head @@ -68,15 +61,26 @@ kfree_skb __kmalloc kmalloc_caches + kmem_cache_alloc kmem_cache_alloc_trace + kmem_cache_create + kmem_cache_destroy + kmem_cache_free kmemdup + kstrdup kvfree kvmalloc_node + __list_add_valid + __list_del_entry_valid __local_bh_enable_ip lock_sock_nested memcpy memset + misc_deregister + misc_register + mod_timer __module_get + module_layout module_put msleep __mutex_init @@ -94,6 +98,7 @@ netif_device_detach netif_tx_stop_all_queues netif_tx_wake_queue + no_llseek noop_llseek nr_cpu_ids param_ops_bool @@ -103,11 +108,11 @@ passthru_features_check pci_disable_device pci_enable_device + pci_iomap pci_read_config_dword __pci_register_driver pci_set_master pci_unregister_driver - __per_cpu_offset perf_trace_buf_alloc perf_trace_run_bpf_submit platform_device_add @@ -117,18 +122,16 @@ platform_device_unregister __platform_driver_register platform_driver_unregister - preempt_count_add - preempt_count_sub - preempt_schedule preempt_schedule_notrace prepare_to_wait_event printk + __put_cred put_device __put_page + __put_task_struct + put_unused_fd queue_delayed_work_on queue_work_on - _raw_read_lock - _raw_read_unlock _raw_spin_lock _raw_spin_lock_bh _raw_spin_lock_irq @@ -143,6 +146,8 @@ refcount_inc_checked register_netdev register_netdevice_notifier + register_virtio_device + register_virtio_driver release_sock remove_wait_queue request_threaded_irq @@ -151,10 +156,10 @@ schedule schedule_timeout schedule_timeout_uninterruptible + scnprintf seq_printf sg_init_one sg_init_table - sg_next skb_clone skb_put sk_free @@ -172,6 +177,7 @@ strstr synchronize_irq synchronize_net + synchronize_rcu system_wq trace_define_field trace_event_buffer_commit @@ -185,7 +191,34 @@ unregister_netdev unregister_netdevice_notifier unregister_netdevice_queue + unregister_virtio_device + unregister_virtio_driver + up_read + up_write + usleep_range + virtio_check_driver_offered_feature + virtio_config_changed + virtio_max_dma_size + virtqueue_add_inbuf + virtqueue_add_outbuf + virtqueue_add_sgs + virtqueue_detach_unused_buf + virtqueue_disable_cb + virtqueue_enable_cb + virtqueue_get_avail_addr + virtqueue_get_buf + virtqueue_get_desc_addr + virtqueue_get_used_addr + virtqueue_get_vring_size + virtqueue_is_broken + virtqueue_kick + virtqueue_kick_prepare + virtqueue_notify vmemmap + vring_create_virtqueue + vring_del_virtqueue + vring_interrupt + vring_transport_features wait_woken __wake_up __warn_printk @@ -193,56 +226,9 @@ ww_mutex_lock_interruptible ww_mutex_unlock -# required by binfmt_misc.ko - bin2hex - bprm_change_interp - clear_inode - __close_fd - copy_strings_kernel - _ctype - current_time - d_drop - default_llseek - dentry_open - d_instantiate - down_write - dput - drop_nlink - filp_close - free_pages - __get_free_pages - get_next_ino - get_tree_single - iput - kernel_read - kill_litter_super - kstrtoint - lockref_get - lookup_one_len - new_inode - open_exec - prepare_binprm - _raw_write_lock - _raw_write_unlock - __register_binfmt - register_filesystem - remove_arg_zero - search_binary_handler - simple_fill_super - simple_pin_fs - simple_read_from_buffer - simple_release_fs - simple_statfs - strchr - string_unescape - strrchr - unregister_binfmt - unregister_filesystem - up_write - would_dump - -# required by blk-mq-virtio.ko - blk_mq_map_queues +# required by ac97_bus.ko + bus_register + bus_unregister # required by dummy-cpufreq.ko cpufreq_generic_attr @@ -253,9 +239,7 @@ device_create_file device_remove_file ktime_get_ts64 - mod_timer platform_device_add_data - scnprintf sg_miter_next sg_miter_start sg_miter_stop @@ -279,7 +263,6 @@ usb_put_dev usb_put_hcd usb_remove_hcd - usleep_range # required by failover.ko netdev_master_upper_dev_link @@ -289,7 +272,6 @@ bus_find_device device_find_child device_match_name - kstrdup platform_bus_type strsep @@ -347,6 +329,92 @@ rtc_tm_to_time64 rtc_update_irq +# required by sdcardfs.ko + __break_lease + call_rcu + clear_inode + clear_nlink + configfs_register_subsystem + configfs_unregister_subsystem + config_group_init + config_group_init_type_name + config_item_init_type_name + copy_fs_struct + _ctype + d_drop + dentry_open + dget_parent + d_invalidate + d_make_root + d_path + dput + d_rehash + d_set_d_op + d_splice_alias + filemap_write_and_wait + filp_close + filp_open + free_fs_struct + fscrypt_register_key_removal_notifier + fscrypt_unregister_key_removal_notifier + fs_parse + fsstack_copy_inode_size + generic_delete_inode + __generic_file_fsync + generic_file_llseek + generic_permission + generic_read_dir + iget5_locked + igrab + init_special_inode + inode_init_once + inode_newsize_ok + iput + iterate_dir + kern_path + kill_anon_super + kstrtouint + kstrtoull + lockref_get + lock_rename + lookup_one_len_unlocked + mntget + names_cachep + notify_change2 + override_creds + path_get + path_put + prepare_creds + ___ratelimit + register_filesystem + revert_creds + seq_puts + setattr_prepare + set_fs_pwd + set_nlink + shrink_dcache_sb + strcasecmp + strncasecmp + strrchr + touch_atime + truncate_inode_pages + truncate_setsize + unlock_new_inode + unlock_rename + unregister_filesystem + vfs_create2 + vfs_fsync_range + vfs_getattr + vfs_get_super + vfs_mkdir2 + vfs_path_lookup + vfs_read + vfs_rename2 + vfs_rmdir2 + vfs_statfs + vfs_unlink2 + vfs_write + # required by snd-ac97-codec.ko pci_read_config_word simple_strtoul @@ -369,7 +437,6 @@ # required by snd-intel8x0.ko ktime_get param_ops_bint - pci_iomap pci_release_regions pci_request_regions pci_write_config_dword @@ -394,15 +461,73 @@ snd_pcm_period_elapsed snd_pcm_set_ops +# required by test_meminit.ko + kmem_cache_alloc_bulk + kmem_cache_free_bulk + vfree + vmalloc + +# required by tpm.ko + alloc_chrdev_region + cdev_device_add + cdev_device_del + cdev_init + __class_create + class_destroy + __compat_only_sysfs_link_entry_to_kobj + del_timer_sync + device_initialize + devm_add_action + down_read + efi + efi_tpm_final_log_size + hash_digest_size + idr_alloc + idr_destroy + idr_get_next + idr_remove + idr_replace + __init_rwsem + jiffies_to_msecs + jiffies_to_usecs + krealloc + memchr_inv + memremap + memunmap + of_find_property + of_get_property + of_property_match_string + physvirt_offset + securityfs_create_dir + securityfs_create_file + securityfs_remove + seq_lseek + seq_open + seq_putc + seq_read + seq_release + seq_write + sysfs_remove_link + unregister_chrdev_region + __usecs_to_jiffies + +# required by tpm_vtpm_proxy.ko + anon_inode_getfile + # required by ttm.ko clear_page copy_page + dev_driver_string devres_add - __devres_alloc_node + devres_alloc_node devres_destroy devres_free + dma_alloc_attrs + dma_direct_map_page + dma_direct_unmap_page dma_fence_enable_sw_signaling dma_fence_signal + dma_free_attrs dma_resv_add_shared_fence dma_resv_copy_fences dma_resv_fini @@ -438,6 +563,9 @@ __memset_io mutex_is_locked nr_swap_pages + preempt_schedule + _raw_read_lock + _raw_read_unlock refcount_inc_not_zero_checked register_shrinker reservation_ww_class @@ -448,7 +576,6 @@ si_meminfo unmap_mapping_range unregister_shrinker - up_read vmalloc_to_page vmap vmf_insert_mixed @@ -565,14 +692,10 @@ drm_universal_plane_init __get_task_comm kmalloc_order_trace - kmem_cache_alloc - kmem_cache_create - kmem_cache_destroy - kmem_cache_free memdup_user - put_unused_fd __sg_alloc_table_from_pages sg_free_table + sg_next strncpy sync_file_create sync_file_get_fence @@ -580,20 +703,9 @@ # required by virtio-rng.ko complete - hwrng_register - hwrng_unregister wait_for_completion wait_for_completion_killable -# required by virtio.ko - add_uevent_var - device_add - device_initialize - driver_register - driver_unregister - ida_destroy - panic - # required by virtio_blk.ko __alloc_disk_node blk_cleanup_queue @@ -609,6 +721,7 @@ blk_mq_start_stopped_hw_queues blk_mq_stop_hw_queue blk_mq_unquiesce_queue + blk_mq_virtio_map_queues blk_put_request blk_queue_alignment_offset blk_queue_flag_set @@ -639,23 +752,6 @@ __sysfs_match_string unregister_blkdev -# required by virtio_crypto.ko - cpu_bit_bitmap - cpu_topology - crypto_ablkcipher_type - crypto_engine_alloc_init - crypto_engine_exit - crypto_engine_start - crypto_finalize_ablkcipher_request - crypto_register_alg - crypto_transfer_ablkcipher_request_to_engine - crypto_unregister_alg - kzfree - scatterwalk_map_and_copy - sg_nents - sg_nents_for_len - try_module_get - # required by virtio_input.ko input_alloc_absinfo input_allocate_device @@ -679,7 +775,6 @@ # required by virtio_net.ko arch_bpf_jit_check_func - bcmp bpf_prog_add bpf_prog_put bpf_prog_sub @@ -690,7 +785,10 @@ __cpuhp_setup_state __cpuhp_state_add_instance __cpuhp_state_remove_instance + cpumask_next cpumask_next_wrap + cpus_read_lock + cpus_read_unlock eth_commit_mac_addr_change eth_prepare_mac_addr_change ethtool_op_get_ts_info @@ -727,8 +825,12 @@ skb_to_sgvec skb_tstamp_tx softnet_data - __this_cpu_preempt_check __tracepoint_xdp_exception + virtqueue_add_inbuf_ctx + virtqueue_enable_cb_delayed + virtqueue_enable_cb_prepare + virtqueue_get_buf_ctx + virtqueue_poll xdp_convert_zc_to_xdp_frame xdp_do_flush_map xdp_do_redirect @@ -739,7 +841,6 @@ xdp_rxq_info_unreg # required by virtio_pci.ko - get_device irq_set_affinity_hint pci_alloc_irq_vectors_affinity pci_find_capability @@ -750,25 +851,18 @@ pci_irq_get_affinity pci_irq_vector pci_read_config_byte + pci_release_region pci_release_selected_regions + pci_request_region pci_request_selected_regions + virtio_device_freeze + virtio_device_restore # required by virtio_pmem.ko nvdimm_bus_register nvdimm_bus_unregister nvdimm_pmem_region_create -# required by virtio_ring.ko - alloc_pages_exact - dma_max_mapping_size - free_pages_exact - kimage_voffset - physvirt_offset - vabits_actual - -# required by vmw_vsock_virtio_transport.ko - synchronize_rcu - # required by vmw_vsock_virtio_transport_common.ko bpf_trace_run10 bpf_trace_run8 @@ -779,14 +873,11 @@ # required by vsock.ko autoremove_wake_function - misc_deregister - misc_register nonseekable_open prandom_u32 prepare_to_wait proto_register proto_unregister - __put_cred _raw_write_lock_bh _raw_write_unlock_bh security_sock_graft diff --git a/abi_gki_aarch64_db845c_whitelist b/abi_gki_aarch64_db845c_whitelist index eb359543eea6..4468dc943e30 100644 --- a/abi_gki_aarch64_db845c_whitelist +++ b/abi_gki_aarch64_db845c_whitelist @@ -1,7 +1,6 @@ [abi_whitelist] # commonly used symbols add_uevent_var - alloc_chrdev_region __alloc_skb alloc_workqueue __arch_copy_from_user @@ -15,25 +14,21 @@ bt_info cancel_delayed_work_sync cancel_work_sync - cdev_device_add - cdev_device_del - cdev_init __cfi_slowpath __check_object_size - __class_register - class_unregister - clk_alpha_pll_regs - clk_branch2_ops clk_bulk_disable clk_bulk_enable clk_bulk_prepare clk_bulk_unprepare clk_disable clk_enable + clk_fixed_factor_ops + clk_fixed_rate_ops clk_get_rate + clk_hw_get_parent + clk_hw_get_rate clk_prepare clk_put - clk_rcg2_ops clk_round_rate clk_set_rate clk_sync_state @@ -49,16 +44,16 @@ cpu_number __cpu_online_mask crc32_le - debug_smp_processor_id + _ctype delayed_work_timer_fn del_timer del_timer_sync destroy_workqueue dev_driver_string _dev_err + dev_fwnode dev_get_regmap device_create_file - device_initialize device_init_wakeup device_property_present device_property_read_string @@ -71,6 +66,7 @@ __dev_kfree_skb_any devm_add_action devm_clk_bulk_get + devm_clk_bulk_get_all devm_clk_get devm_clk_get_optional devm_clk_hw_register @@ -79,6 +75,7 @@ devm_ioremap_resource devm_kfree devm_kmalloc + devm_of_clk_add_hw_provider __devm_of_phy_provider_register devm_of_platform_populate devm_phy_create @@ -92,13 +89,15 @@ devm_reset_control_array_get __devm_reset_control_get devm_reset_controller_register - devres_add - __devres_alloc_node - devres_free + devm_usb_get_phy_by_phandle + devm_watchdog_register_device dev_set_name _dev_warn disable_irq disable_irq_nosync + divider_get_val + divider_recalc_rate + divider_round_rate_parent dma_alloc_attrs dma_direct_map_page dma_direct_map_sg @@ -114,6 +113,7 @@ dma_set_coherent_mask dma_set_mask do_SAK + down_write driver_unregister drm_add_edid_modes drm_atomic_helper_connector_destroy_state @@ -137,6 +137,7 @@ extcon_unregister_notifier find_next_bit finish_wait + fput free_irq generic_handle_irq generic_mii_ioctl @@ -152,7 +153,6 @@ __hci_cmd_sync hci_recv_frame hdmi_audio_infoframe_init - hrtimer_cancel hrtimer_init hrtimer_start_range_ns i2c_add_adapter @@ -172,6 +172,7 @@ irq_set_chip_and_handler_name irq_set_chip_data irq_set_irq_wake + irq_to_desc jiffies kfree kfree_skb @@ -181,18 +182,17 @@ kmem_cache_alloc_trace kmemdup kstrdup - kthread_destroy_worker - kthread_queue_work + kstrtouint ktime_get ktime_get_mono_fast_ns + __list_add_valid + __list_del_entry_valid memcpy memset mii_ethtool_gset mii_nway_restart - misc_deregister - misc_register mod_timer - module_put + module_layout __msecs_to_jiffies msleep msm_pinctrl_probe @@ -241,7 +241,6 @@ pci_set_mwi pci_unregister_driver pci_write_config_byte - __per_cpu_offset perf_trace_buf_alloc perf_trace_run_bpf_submit phy_exit @@ -279,14 +278,12 @@ __pm_runtime_set_status __pm_runtime_suspend __pm_runtime_use_autosuspend - preempt_count_sub preempt_schedule preempt_schedule_notrace prepare_to_wait_event printk put_device - qcom_cc_map - qcom_cc_really_probe + __put_task_struct qcom_scm_is_available queue_delayed_work_on queue_work_on @@ -320,7 +317,7 @@ request_threaded_irq reset_control_assert reset_control_deassert - sched_setscheduler + rpmh_write_async schedule_timeout schedule_timeout_uninterruptible scnprintf @@ -360,7 +357,6 @@ trace_handle_return trace_raw_output_prep trace_seq_printf - try_module_get tty_flip_buffer_push __tty_insert_flip_char tty_termios_encode_baud_rate @@ -373,8 +369,8 @@ uart_unregister_driver uart_update_timeout uart_write_wakeup - unregister_chrdev_region unregister_reboot_notifier + up_write usb_add_hcd usb_amd_dev_put usb_amd_quirk_pll_check @@ -432,121 +428,23 @@ wait_for_completion_timeout __wake_up __warn_printk + watchdog_init_timeout -# required by asix.ko - eth_mac_addr - eth_platform_get_mac_address - genphy_resume - get_random_bytes - mdiobus_alloc_size - mdiobus_free - __mdiobus_register - mdiobus_unregister - memmove - mii_check_media - mii_link_ok - netdev_err - phy_connect - phy_disconnect - phy_ethtool_get_link_ksettings - phy_ethtool_nway_reset - phy_ethtool_set_link_ksettings - phy_mii_ioctl - phy_print_status - phy_start - phy_stop - skb_copy_expand - usbnet_change_mtu - usbnet_get_drvinfo - usbnet_get_link - usbnet_get_link_ksettings - usbnet_set_link_ksettings - usbnet_unlink_rx_urbs - -# required by ax88179_178a.ko - ethtool_op_get_link - mii_ethtool_get_link_ksettings - mii_ethtool_set_link_ksettings - netif_carrier_on - pskb_expand_head - skb_trim +# required by regmap-spmi.ko + __devm_regmap_init + __regmap_init + spmi_ext_register_read + spmi_ext_register_readl + spmi_ext_register_write + spmi_ext_register_writel + spmi_register_read + spmi_register_write + spmi_register_zero_write # required by btqca.ko __hci_cmd_send __hci_cmd_sync_ev -# required by clk-scmi.ko - clk_hw_set_rate_range - devm_of_clk_add_hw_provider - scmi_driver_register - scmi_driver_unregister - -# required by dispcc-sdm845.ko - clk_alpha_pll_fabia_ops - clk_byte2_ops - clk_fabia_pll_configure - clk_pixel_ops - clk_rcg2_shared_ops - clk_regmap_div_ops - -# required by dwc3-qcom.ko - devm_extcon_register_notifier - of_clk_get_parent_count - -# required by dwc3.ko - device_property_read_u8_array - devm_kmemdup - extcon_find_edev_by_node - extcon_get_extcon_dev - of_usb_get_phy_mode - phy_pm_runtime_get_sync - phy_pm_runtime_put_sync - platform_get_irq_byname_optional - system_freezable_wq - usb_add_gadget_udc - usb_decode_ctrl - usb_del_gadget_udc - usb_ep_set_maxpacket_limit - usb_gadget_giveback_request - usb_gadget_map_request_by_dev - usb_gadget_set_state - usb_gadget_udc_reset - usb_gadget_unmap_request_by_dev - usb_get_maximum_speed - -# required by ehci-hcd.ko - device_remove_file - down_write - ehci_cf_port_reset_rwsem - kstrtouint - ktime_get_with_offset - up_write - usb_for_each_dev - -# required by ehci-pci.ko - pci_clear_mwi - pci_find_capability - usb_amd_hang_symptom_quirk - -# required by ehci-platform.ko - device_pm_wait_for_dev - usb_of_get_companion_dev - -# required by extcon-usb-gpio.ko - devm_extcon_dev_allocate - devm_extcon_dev_register - extcon_set_state_sync - gpiod_get_value_cansleep - gpiod_set_debounce - gpiod_to_irq - system_power_efficient_wq - -# required by gcc-msm8998.ko - clk_alpha_pll_ops - clk_alpha_pll_postdiv_ops - clk_fixed_factor_ops - clk_rcg2_floor_ops - # required by hci_uart.ko bit_wait_timeout hci_alloc_dev @@ -563,7 +461,6 @@ __percpu_init_rwsem __percpu_up_read percpu_up_write - preempt_count_add serdev_device_close __serdev_device_driver_register serdev_device_open @@ -573,7 +470,6 @@ serdev_device_wait_until_sent serdev_device_write_buf serdev_device_write_flush - __this_cpu_preempt_check tty_driver_flush_buffer tty_ldisc_flush tty_register_ldisc @@ -582,14 +478,41 @@ tty_unthrottle wake_up_bit -# required by i2c-qcom-geni.ko - i2c_get_dma_safe_msg_buf - i2c_put_dma_safe_msg_buf - of_machine_is_compatible +# required by clk-scmi.ko + clk_hw_set_rate_range + scmi_driver_register + scmi_driver_unregister -# required by i2c-qup.ko - _dev_notice - __usecs_to_jiffies +# required by clk-qcom.ko + __clk_determine_rate + __clk_get_name + clk_hw_get_flags + clk_hw_get_name + clk_hw_get_num_parents + clk_hw_get_parent_by_index + clk_hw_round_rate + __clk_is_enabled + __clk_mux_determine_rate_closest + divider_ro_round_rate_parent + of_find_node_opts_by_path + of_genpd_add_provider_onecell + of_genpd_del_provider + of_prop_next_u32 + pm_genpd_add_subdomain + pm_genpd_init + pm_genpd_remove_subdomain + +# required by clk-rpmh.ko + clk_hw_is_prepared + +# required by extcon-usb-gpio.ko + devm_extcon_dev_allocate + devm_extcon_dev_register + extcon_set_state_sync + gpiod_get_value_cansleep + gpiod_set_debounce + gpiod_to_irq + system_power_efficient_wq # required by lt9611.ko __devm_regmap_init_i2c @@ -606,13 +529,7 @@ of_find_mipi_dsi_host_by_node regmap_multi_reg_write -# required by mdt_loader.ko - qcom_scm_pas_init_image - qcom_scm_pas_mem_setup - request_firmware_into_buf - # required by msm.ko - __alloc_pages_nodemask __bitmap_andnot __bitmap_weight bpf_trace_run5 @@ -620,8 +537,6 @@ bpf_trace_run8 clk_get clk_get_parent - clk_hw_get_parent - clk_hw_get_rate clk_hw_register clk_hw_register_divider clk_hw_register_fixed_factor @@ -638,12 +553,10 @@ component_master_add_with_match component_master_del component_unbind_all - _ctype devfreq_recommended_opp devfreq_resume_device devfreq_suspend_device device_find_child - devm_clk_bulk_get_all devm_clk_register devm_devfreq_add_device devm_ioremap_nocache @@ -661,9 +574,6 @@ dev_pm_opp_of_add_table dev_pm_opp_put dev_pm_opp_set_supported_hw - divider_get_val - divider_recalc_rate - divider_round_rate_parent dma_buf_vunmap dma_fence_context_alloc dma_fence_init @@ -834,8 +744,6 @@ fd_install find_next_zero_bit flush_workqueue - fput - __free_pages get_pid_task get_unused_fd_flags gpiod_direction_input @@ -853,17 +761,17 @@ iommu_detach_device iommu_domain_alloc iommu_domain_free - iommu_map iommu_map_sg iommu_present iommu_set_fault_handler iommu_unmap irq_domain_xlate_onecell - irq_to_desc kasprintf kstrdup_quotable_cmdline kthread_create_on_node + kthread_destroy_worker __kthread_init_worker + kthread_queue_work kthread_worker_fn ktime_get_real_ts64 kvfree @@ -899,7 +807,6 @@ param_ops_charp platform_bus_type put_pid - __put_task_struct put_unused_fd qcom_scm_hdcp_available qcom_scm_hdcp_req @@ -916,6 +823,7 @@ request_firmware_direct reservation_ww_class round_jiffies_up + sched_setscheduler sg_free_table shmem_truncate_range strncpy @@ -936,28 +844,98 @@ ww_mutex_lock_interruptible ww_mutex_unlock -# required by msm_serial.ko - iomem_resource - __release_region - __request_region - tty_termios_baud_rate +# required by qcom_hwspinlock.ko + devm_regmap_field_alloc + hwspin_lock_register + hwspin_lock_unregister + regmap_field_read + regmap_field_update_bits_base + +# required by i2c-qcom-geni.ko + i2c_get_dma_safe_msg_buf + i2c_put_dma_safe_msg_buf + of_machine_is_compatible + +# required by i2c-qup.ko + _dev_notice + __usecs_to_jiffies + +# required by pm8941-pwrkey.ko + devm_input_allocate_device + input_event + input_register_device + input_set_capability + +# required by qnoc-sdm845.ko + icc_link_create + icc_node_add + icc_node_create + icc_node_del + icc_node_destroy + icc_provider_add + icc_provider_del + of_icc_xlate_onecell + rpmh_invalidate + rpmh_write_batch + +# required by qcom-spmi-pmic.ko + __spmi_driver_register + +# required by sdhci-msm.ko + mmc_of_parse + mmc_send_tuning + regulator_is_supported_voltage + sdhci_add_host + sdhci_enable_clk + sdhci_get_property + sdhci_pltfm_free + sdhci_pltfm_init + sdhci_remove_host + sdhci_reset + sdhci_set_bus_width + +# required by asix.ko + eth_mac_addr + eth_platform_get_mac_address + genphy_resume + get_random_bytes + mdiobus_alloc_size + mdiobus_free + __mdiobus_register + mdiobus_unregister + memmove + mii_check_media + mii_link_ok + netdev_err + phy_connect + phy_disconnect + phy_ethtool_get_link_ksettings + phy_ethtool_nway_reset + phy_ethtool_set_link_ksettings + phy_mii_ioctl + phy_print_status + phy_start + phy_stop + skb_copy_expand + usbnet_change_mtu + usbnet_get_drvinfo + usbnet_get_link + usbnet_get_link_ksettings + usbnet_set_link_ksettings + usbnet_unlink_rx_urbs + +# required by ax88179_178a.ko + ethtool_op_get_link + mii_ethtool_get_link_ksettings + mii_ethtool_set_link_ksettings + netif_carrier_on + pskb_expand_head + skb_trim # required by nvmem_qfprom.ko devm_nvmem_register -# required by ohci-hcd.ko - flush_work - gen_pool_dma_alloc_align - gen_pool_dma_zalloc_align - gen_pool_free_owner - sb800_prefetch - -# required by ohci-pci.ko - pci_get_slot - usb_amd_prefetch_quirk - # required by phy-qcom-qmp.ko - clk_fixed_rate_ops of_clk_get_by_name of_clk_hw_simple_get of_iomap @@ -988,21 +966,102 @@ # required by pinctrl-spmi-mpp.ko platform_irq_count -# required by pm8941-pwrkey.ko - devm_input_allocate_device - input_event - input_register_device - input_set_capability +# required by reboot-mode.ko + devres_add + devres_alloc_node + devres_free + devres_release + kfree_const + kstrdup_const # required by qcom-rpmh-regulator.ko of_get_regulator_init_data of_node_name_eq regulator_list_voltage_linear_range rpmh_write - rpmh_write_async -# required by qcom-spmi-pmic.ko - __spmi_driver_register +# required by qcom_spmi-regulator.ko + jiffies_to_usecs + regulator_disable_regmap + regulator_enable_regmap + regulator_is_enabled_regmap + smp_call_function_single + +# required by rtc-pm8xxx.ko + devm_request_any_context_irq + devm_rtc_device_register + rtc_time64_to_tm + rtc_tm_to_time64 + rtc_update_irq + rtc_valid_tm + +# required by ufs-qcom.ko + print_hex_dump + ufshcd_dme_get_attr + ufshcd_dme_set_attr + ufshcd_dump_regs + ufshcd_get_local_unipro_ver + ufshcd_get_pwr_dev_param + ufshcd_hold + ufshcd_pltfrm_init + ufshcd_pltfrm_resume + ufshcd_pltfrm_runtime_idle + ufshcd_pltfrm_runtime_resume + ufshcd_pltfrm_runtime_suspend + ufshcd_pltfrm_shutdown + ufshcd_pltfrm_suspend + ufshcd_release + ufshcd_remove + ufshcd_uic_hibern8_enter + ufshcd_uic_hibern8_exit + +# required by mdt_loader.ko + qcom_scm_pas_init_image + qcom_scm_pas_mem_setup + request_firmware_into_buf + +# required by rmtfs_mem.ko + alloc_chrdev_region + cdev_device_add + cdev_device_del + cdev_init + __class_register + class_unregister + default_llseek + device_initialize + devm_memremap + of_reserved_mem_lookup + qcom_scm_assign_mem + remap_pfn_range + unregister_chrdev_region + +# required by smem.ko + devm_ioremap_wc + hwspin_lock_free + hwspin_lock_request_specific + __hwspin_lock_timeout + __hwspin_unlock + of_hwspin_lock_get_id + +# required by smsm.ko + handle_nested_irq + irq_domain_xlate_twocell + qcom_smem_state_register + qcom_smem_state_unregister + +# required by spmi-pmic-arb.ko + handle_edge_irq + irq_domain_free_irqs_common + irq_domain_set_info + spmi_controller_add + spmi_controller_alloc + spmi_controller_remove + +# required by msm_serial.ko + iomem_resource + __release_region + __request_region + tty_termios_baud_rate # required by qcom_geni_serial.ko console_stop @@ -1017,34 +1076,217 @@ uart_parse_options uart_set_options -# required by qcom_hwspinlock.ko - devm_regmap_field_alloc - hwspin_lock_register - hwspin_lock_unregister - regmap_field_read - regmap_field_update_bits_base +# required by ulpi.ko + bus_register + bus_unregister + driver_register + of_device_modalias + of_device_request_module + of_device_uevent_modalias + __request_module -# required by qcom_spmi-regulator.ko - jiffies_to_usecs - regulator_disable_regmap - regulator_enable_regmap - regulator_is_enabled_regmap - smp_call_function_single +# required by dwc3-qcom.ko + devm_extcon_register_notifier + of_clk_get_parent_count -# required by qnoc-sdm845.ko - icc_link_create - icc_node_add - icc_node_create - icc_node_del - icc_node_destroy - icc_provider_add - icc_provider_del - of_icc_xlate_onecell - rpmh_invalidate - rpmh_write_batch +# required by dwc3.ko + device_property_read_u8_array + devm_usb_get_phy + extcon_find_edev_by_node + extcon_get_extcon_dev + of_usb_get_phy_mode + phy_pm_runtime_get_sync + phy_pm_runtime_put_sync + platform_get_irq_byname_optional + system_freezable_wq + usb_add_gadget_udc + usb_decode_ctrl + usb_del_gadget_udc + usb_ep_set_maxpacket_limit + usb_gadget_giveback_request + usb_gadget_map_request_by_dev + usb_gadget_set_state + usb_gadget_udc_reset + usb_gadget_unmap_request_by_dev + usb_get_maximum_speed + +# required by ehci-hcd.ko + device_remove_file + ehci_cf_port_reset_rwsem + hrtimer_cancel + ktime_get_with_offset + usb_for_each_dev + +# required by ehci-pci.ko + pci_clear_mwi + pci_find_capability + usb_amd_hang_symptom_quirk + +# required by ehci-platform.ko + device_pm_wait_for_dev + usb_of_get_companion_dev + +# required by ohci-hcd.ko + flush_work + gen_pool_dma_alloc_align + gen_pool_dma_zalloc_align + gen_pool_free_owner + sb800_prefetch + +# required by ohci-pci.ko + pci_get_slot + usb_amd_prefetch_quirk + +# required by xhci-hcd.ko + add_timer + cancel_delayed_work + mod_delayed_work_on + __num_online_cpus + param_ops_ullong + pci_alloc_irq_vectors_affinity + pci_free_irq_vectors + pci_irq_vector + radix_tree_maybe_preload + sg_pcopy_from_buffer + sg_pcopy_to_buffer + trace_print_symbols_seq + usb_amd_pt_check_port + usb_asmedia_modifyflowcontrol + usb_disable_xhci_ports + usb_hcd_irq + usb_hcd_map_urb_for_dma + usb_wakeup_notification + wait_for_completion + +# required by xhci-pci-renesas.ko + device_release_driver + pci_dev_get + pci_write_config_dword + request_firmware_nowait + +# required by xhci-pci.ko + pci_d3cold_disable + pci_set_power_state + usb_create_shared_hcd + usb_enable_intel_xhci_ports + +# required by xhci-plat-hcd.ko + of_usb_host_tpl_support + pci_bus_type + __usb_create_hcd + +# required by roles.ko + __class_create + class_destroy + class_find_device + device_connection_find_match + device_match_fwnode + device_match_name + fwnode_connection_find_match + fwnode_get_parent + fwnode_property_present + kstrtobool + module_put + __sysfs_match_string + try_module_get + +# required by qcom-wdt.ko + platform_get_irq_optional + +# required by sdcardfs.ko + __break_lease + call_rcu + clear_inode + clear_nlink + configfs_register_subsystem + configfs_unregister_subsystem + config_group_init + config_group_init_type_name + config_item_init_type_name + copy_fs_struct + d_drop + dentry_open + dget_parent + d_invalidate + d_make_root + d_path + dput + d_rehash + d_set_d_op + d_splice_alias + filemap_write_and_wait + filp_close + filp_open + free_fs_struct + fscrypt_register_key_removal_notifier + fscrypt_unregister_key_removal_notifier + fs_parse + fsstack_copy_inode_size + generic_delete_inode + __generic_file_fsync + generic_file_llseek + generic_permission + generic_read_dir + iget5_locked + igrab + init_special_inode + inode_init_once + inode_newsize_ok + iput + iterate_dir + kern_path + kill_anon_super + kmem_cache_alloc + kmem_cache_create + kmem_cache_destroy + kmem_cache_free + kstrtoull + lockref_get + lock_rename + lookup_one_len_unlocked + mntget + names_cachep + notify_change2 + override_creds + path_get + path_put + prepare_creds + __put_cred + __rcu_read_lock + __rcu_read_unlock + register_filesystem + revert_creds + setattr_prepare + set_fs_pwd + set_nlink + shrink_dcache_sb + strcasecmp + strncasecmp + strrchr + synchronize_rcu + touch_atime + truncate_inode_pages + truncate_setsize + unlock_new_inode + unlock_rename + unregister_filesystem + vfs_create2 + vfs_fsync_range + vfs_getattr + vfs_get_super + vfs_mkdir2 + vfs_path_lookup + vfs_read + vfs_rename2 + vfs_rmdir2 + vfs_statfs + vfs_unlink2 + vfs_write # required by qrtr-tun.ko _copy_to_iter + misc_deregister + misc_register schedule # required by qrtr.ko @@ -1087,78 +1329,6 @@ sock_register sock_unregister -# required by reboot-mode.ko - devres_release - kfree_const - kstrdup_const - -# required by regmap-spmi.ko - __devm_regmap_init - __regmap_init - spmi_ext_register_read - spmi_ext_register_readl - spmi_ext_register_write - spmi_ext_register_writel - spmi_register_read - spmi_register_write - spmi_register_zero_write - -# required by rmtfs_mem.ko - default_llseek - devm_memremap - of_reserved_mem_lookup - qcom_scm_assign_mem - remap_pfn_range - -# required by roles.ko - __class_create - class_destroy - class_find_device - dev_fwnode - device_connection_find_match - device_match_fwnode - device_match_name - fwnode_connection_find_match - fwnode_get_parent - fwnode_property_present - kstrtobool - __sysfs_match_string - -# required by rtc-pm8xxx.ko - devm_request_any_context_irq - devm_rtc_device_register - rtc_time64_to_tm - rtc_tm_to_time64 - rtc_update_irq - rtc_valid_tm - -# required by sdhci-msm.ko - mmc_of_parse - mmc_send_tuning - regulator_is_supported_voltage - sdhci_add_host - sdhci_enable_clk - sdhci_get_property - sdhci_pltfm_free - sdhci_pltfm_init - sdhci_remove_host - sdhci_reset - sdhci_set_bus_width - -# required by smem.ko - devm_ioremap_wc - hwspin_lock_free - hwspin_lock_request_specific - __hwspin_lock_timeout - __hwspin_unlock - of_hwspin_lock_get_id - -# required by smsm.ko - handle_nested_irq - irq_domain_xlate_twocell - qcom_smem_state_register - qcom_smem_state_unregister - # required by snd-soc-hdmi-codec.ko devm_snd_soc_register_component snd_ctl_add @@ -1169,89 +1339,3 @@ snd_pcm_hw_constraint_eld snd_soc_dapm_add_routes snd_soc_jack_report - -# required by spmi-pmic-arb.ko - handle_edge_irq - irq_domain_free_irqs_common - irq_domain_set_info - spmi_controller_add - spmi_controller_alloc - spmi_controller_remove - -# required by ufs-qcom.ko - print_hex_dump - ufshcd_dme_get_attr - ufshcd_dme_set_attr - ufshcd_dump_regs - ufshcd_get_local_unipro_ver - ufshcd_get_pwr_dev_param - ufshcd_hold - ufshcd_pltfrm_init - ufshcd_pltfrm_resume - ufshcd_pltfrm_runtime_idle - ufshcd_pltfrm_runtime_resume - ufshcd_pltfrm_runtime_suspend - ufshcd_pltfrm_shutdown - ufshcd_pltfrm_suspend - ufshcd_release - ufshcd_remove - ufshcd_uic_hibern8_enter - ufshcd_uic_hibern8_exit - -# required by ulpi.ko - bus_register - bus_unregister - driver_register - of_device_modalias - of_device_request_module - of_device_uevent_modalias - __request_module - -# required by watchdog.ko - devm_register_reboot_notifier - ida_alloc_range - ida_destroy - ida_free - kthread_cancel_work_sync - kthread_create_worker - __module_get - register_restart_handler - stream_open - unregister_restart_handler - -# required by xhci-hcd.ko - add_timer - cancel_delayed_work - mod_delayed_work_on - __num_online_cpus - param_ops_ullong - pci_alloc_irq_vectors_affinity - pci_free_irq_vectors - pci_irq_vector - radix_tree_maybe_preload - sg_pcopy_from_buffer - sg_pcopy_to_buffer - usb_amd_pt_check_port - usb_asmedia_modifyflowcontrol - usb_disable_xhci_ports - usb_hcd_irq - usb_hcd_map_urb_for_dma - usb_wakeup_notification - wait_for_completion - -# required by xhci-pci-renesas.ko - device_release_driver - pci_dev_get - pci_write_config_dword - request_firmware_nowait - -# required by xhci-pci.ko - pci_d3cold_disable - pci_set_power_state - usb_create_shared_hcd - usb_enable_intel_xhci_ports - -# required by xhci-plat-hcd.ko - of_usb_host_tpl_support - pci_bus_type - __usb_create_hcd diff --git a/abi_gki_aarch64_goldfish_whitelist b/abi_gki_aarch64_goldfish_whitelist new file mode 100644 index 000000000000..260cb5259500 --- /dev/null +++ b/abi_gki_aarch64_goldfish_whitelist @@ -0,0 +1,1160 @@ +[abi_whitelist] +# commonly used symbols + __alloc_disk_node + alloc_etherdev_mqs + alloc_netdev_mqs + __alloc_pages_nodemask + __alloc_percpu_gfp + __alloc_skb + alloc_workqueue + arch_bpf_jit_check_func + __arch_copy_from_user + __arch_copy_to_user + arm64_const_caps_ready + bcmp + bio_alloc_bioset + blk_cleanup_queue + blk_queue_flag_set + blk_queue_write_cache + bpf_prog_put + bpf_stats_enabled_key + bpf_trace_run2 + bpf_trace_run3 + bpf_warn_invalid_xdp_action + build_skb + call_netdevice_notifiers + call_rcu + cancel_delayed_work_sync + cancel_work_sync + capable + __cfi_slowpath + __check_object_size + __class_create + class_destroy + complete + __const_udelay + consume_skb + cpu_hwcap_keys + cpu_hwcaps + cpumask_next + cpu_number + __cpu_online_mask + __cpu_possible_mask + _ctype + delayed_work_timer_fn + del_gendisk + del_timer + del_timer_sync + destroy_workqueue + _dev_err + device_add_disk + device_create + device_unregister + _dev_info + __dev_kfree_skb_any + devm_ioremap + devm_kfree + devm_kmalloc + devm_request_threaded_irq + dev_queue_xmit + dev_set_mtu + dev_set_name + _dev_warn + dma_alloc_attrs + dma_fence_context_alloc + dma_fence_init + dma_fence_release + dma_fence_signal_locked + dma_fence_wait_timeout + dma_free_attrs + dma_resv_add_excl_fence + dma_set_coherent_mask + dma_set_mask + ether_setup + eth_mac_addr + __ethtool_get_link_ksettings + ethtool_op_get_link + ethtool_op_get_ts_info + eth_type_trans + eth_validate_addr + event_triggers_call + fd_install + find_next_bit + finish_wait + flush_work + flush_workqueue + fput + free_irq + free_netdev + __free_pages + free_pages + free_percpu + fs_bio_set + get_device + __get_free_pages + get_random_bytes + get_unused_fd_flags + ida_alloc_range + ida_free + init_net + init_timer_key + init_wait_entry + __init_waitqueue_head + input_allocate_device + input_event + input_free_device + input_register_device + input_set_abs_params + input_unregister_device + __ioremap + iounmap + jiffies + jiffies_to_msecs + kasprintf + kfree + kfree_skb + kimage_vaddr + kimage_voffset + __kmalloc + kmalloc_caches + kmem_cache_alloc + kmem_cache_alloc_trace + kmem_cache_create + kmem_cache_destroy + kmem_cache_free + kmemdup + kobject_add + kobject_create_and_add + kobject_del + kobject_init + kobject_init_and_add + kobject_put + kobject_uevent + kstrdup + kstrtouint + kstrtoull + ktime_get_mono_fast_ns + ktime_get_raw_ts64 + ktime_get_real_seconds + ktime_get_real_ts64 + ktime_get_ts64 + ktime_get_with_offset + kvfree + kvmalloc_node + __list_add_valid + __list_del_entry_valid + __local_bh_enable_ip + memcpy + memmove + memset + misc_deregister + misc_register + mod_timer + module_layout + module_put + __msecs_to_jiffies + msleep + __mutex_init + mutex_lock + mutex_lock_interruptible + mutex_trylock + mutex_unlock + napi_complete_done + napi_disable + napi_gro_receive + napi_hash_del + __napi_schedule + napi_schedule_prep + __netdev_alloc_skb + netdev_err + netdev_increment_features + netdev_info + netdev_master_upper_dev_link + netdev_rx_handler_register + netdev_rx_handler_unregister + netdev_update_features + netdev_upper_dev_unlink + netif_carrier_off + netif_carrier_on + netif_device_detach + netif_napi_add + netif_napi_del + netif_rx + netif_tx_stop_all_queues + netif_tx_wake_queue + net_ratelimit + nf_conntrack_destroy + __nla_parse + nla_put_64bit + nla_put + nr_cpu_ids + param_ops_bool + param_ops_int + param_ops_uint + passthru_features_check + pci_disable_device + pci_enable_device + pci_read_config_byte + pci_read_config_dword + __pci_register_driver + pci_release_region + pci_request_region + pci_set_master + pci_unregister_driver + __per_cpu_offset + perf_trace_buf_alloc + perf_trace_run_bpf_submit + physvirt_offset + platform_device_add + platform_device_alloc + platform_device_del + platform_device_put + platform_device_unregister + __platform_driver_register + platform_driver_unregister + platform_get_irq + platform_get_resource + __pm_runtime_suspend + preempt_schedule + preempt_schedule_notrace + prepare_to_wait_event + printk + __pskb_pull_tail + put_device + put_disk + __put_page + __put_task_struct + put_unused_fd + queue_delayed_work_on + queue_work_on + ___ratelimit + _raw_spin_lock + _raw_spin_lock_bh + _raw_spin_lock_irq + _raw_spin_lock_irqsave + _raw_spin_unlock + _raw_spin_unlock_bh + _raw_spin_unlock_irq + _raw_spin_unlock_irqrestore + __rcu_read_lock + __rcu_read_unlock + refcount_dec_and_test_checked + refcount_inc_checked + refcount_inc_not_zero_checked + regcache_sync + register_blkdev + register_netdev + register_netdevice + register_netdevice_notifier + register_virtio_device + register_virtio_driver + remap_pfn_range + __request_module + request_threaded_irq + revalidate_disk + rhashtable_destroy + rhashtable_init + rhashtable_insert_slow + __rht_bucket_nested + rht_bucket_nested + rht_bucket_nested_insert + rtnl_is_locked + rtnl_link_register + rtnl_link_unregister + rtnl_lock + rtnl_unlock + sched_clock + schedule + schedule_timeout + scnprintf + seq_printf + set_disk_ro + set_page_dirty + sg_init_one + sg_init_table + simple_strtoul + skb_add_rx_frag + skb_clone + skb_copy_bits + skb_pull + skb_push + skb_put + skb_trim + skb_tstamp_tx + snd_card_register + snd_ctl_enum_info + snd_ctl_sync_vmaster + snd_device_new + snd_pci_quirk_lookup + snd_pcm_add_chmap_ctls + snd_pcm_period_elapsed + snprintf + sort + sprintf + sscanf + __stack_chk_fail + __stack_chk_guard + strchr + strcmp + strcpy + strlcpy + strlen + strncmp + strncpy + submit_bio + sync_file_create + synchronize_irq + synchronize_net + synchronize_rcu + sysfs_create_group + sysfs_create_link + sysfs_remove_group + sysfs_remove_link + system_wq + trace_define_field + trace_event_buffer_commit + trace_event_buffer_reserve + trace_event_ignore_this_pid + trace_event_raw_init + trace_event_reg + trace_handle_return + __tracepoint_xdp_exception + trace_raw_output_prep + trace_seq_printf + try_module_get + unregister_blkdev + unregister_netdev + unregister_netdevice_notifier + unregister_netdevice_queue + unregister_virtio_device + unregister_virtio_driver + usleep_range + vabits_actual + virtio_check_driver_offered_feature + virtio_config_changed + virtio_max_dma_size + virtqueue_add_inbuf + virtqueue_add_outbuf + virtqueue_add_sgs + virtqueue_detach_unused_buf + virtqueue_disable_cb + virtqueue_enable_cb + virtqueue_get_avail_addr + virtqueue_get_buf + virtqueue_get_desc_addr + virtqueue_get_used_addr + virtqueue_get_vring_size + virtqueue_is_broken + virtqueue_kick + virtqueue_kick_prepare + virtqueue_notify + vmemmap + vring_create_virtqueue + vring_del_virtqueue + vring_interrupt + vring_transport_features + wait_for_completion + __wake_up + __warn_printk + ww_mutex_lock_interruptible + ww_mutex_unlock + xdp_convert_zc_to_xdp_frame + xdp_do_flush_map + xdp_do_redirect + xdp_return_frame + xdp_return_frame_rx_napi + xdp_rxq_info_reg + xdp_rxq_info_reg_mem_model + xdp_rxq_info_unreg + +# required by bridge.ko + arp_send + arp_tbl + bitmap_free + bitmap_zalloc + brioctl_set + call_usermodehelper + clock_t_to_jiffies + csum_ipv6_magic + csum_partial + dev_disable_lro + __dev_get_by_index + __dev_get_by_name + dev_get_flags + dev_get_iflink + dev_pre_changeaddr_notify + dev_set_allmulti + dev_set_promiscuity + dev_uc_add + dev_uc_del + find_next_zero_bit + inet_confirm_addr + ipv6_chk_addr + ipv6_stub + is_skb_forwardable + jiffies_to_clock_t + kstrndup + mac_pton + mod_delayed_work_on + ndo_dflt_fdb_dump + neigh_destroy + neigh_lookup + netdev_master_upper_dev_get + netdev_notice + netdev_state_change + netdev_walk_all_upper_dev_rcu + netif_receive_skb + netif_rx_ni + net_ns_get_ownership + nf_hooks_needed + nla_find + __nlmsg_put + ns_capable + rcu_barrier + register_pernet_subsys + round_jiffies + rtnl_af_register + rtnl_af_unregister + rtnl_notify + rtnl_set_sk_err + rtnl_trylock + __skb_warn_lro_forwarding + sysfs_create_bin_file + sysfs_create_file_ns + sysfs_remove_bin_file + sysfs_rename_link_ns + system_long_wq + __tracepoint_br_fdb_add + __tracepoint_br_fdb_external_learn_add + __tracepoint_br_fdb_update + __tracepoint_fdb_delete + unregister_netdevice_many + unregister_pernet_subsys + +# required by dummy-cpufreq.ko + cpufreq_generic_attr + cpufreq_register_driver + cpufreq_unregister_driver + +# required by dummy_hcd.ko + device_create_file + device_remove_file + platform_device_add_data + sg_miter_next + sg_miter_start + sg_miter_stop + strstr + usb_add_gadget_udc + usb_add_hcd + usb_create_hcd + usb_create_shared_hcd + usb_del_gadget_udc + usb_disabled + usb_ep_set_maxpacket_limit + usb_gadget_giveback_request + usb_gadget_udc_reset + usb_get_dev + usb_hcd_check_unlink_urb + usb_hcd_giveback_urb + usb_hcd_is_primary_hcd + usb_hcd_link_urb_to_ep + usb_hcd_poll_rh_status + usb_hcd_resume_root_hub + usb_hcd_unlink_urb_from_ep + usb_put_dev + usb_put_hcd + usb_remove_hcd + +# required by goldfish_address_space.ko + kzfree + memremap + memunmap + +# required by goldfish_battery.ko + power_supply_changed + power_supply_get_drvdata + power_supply_register + power_supply_unregister + +# required by goldfish_pipe.ko + get_user_pages_fast + tasklet_init + tasklet_kill + __tasklet_schedule + +# required by goldfish_rotary.ko + devm_input_allocate_device + +# required by goldfish_sync.ko + __close_fd + dma_fence_default_wait + dma_fence_free + +# required by llc.ko + dev_add_pack + dev_remove_pack + kfree_call_rcu + pskb_trim_rcsum_slow + +# required by mac80211_hwsim.ko + __cfg80211_alloc_event_skb + __cfg80211_alloc_reply_skb + __cfg80211_send_event_skb + cfg80211_vendor_cmd_reply + dev_alloc_name + device_bind_driver + device_release_driver + dst_release + genlmsg_put + genl_notify + genl_register_family + genl_unregister_family + hrtimer_cancel + hrtimer_forward + hrtimer_init + hrtimer_start_range_ns + ieee80211_alloc_hw_nm + ieee80211_beacon_get_tim + ieee80211_csa_finish + ieee80211_csa_is_complete + ieee80211_free_hw + ieee80211_free_txskb + ieee80211_get_tx_rates + ieee80211_iterate_active_interfaces_atomic + ieee80211_probereq_get + ieee80211_queue_delayed_work + ieee80211_ready_on_channel + ieee80211_register_hw + ieee80211_remain_on_channel_expired + ieee80211_rx_irqsafe + ieee80211_scan_completed + ieee80211_start_tx_ba_cb_irqsafe + ieee80211_stop_tx_ba_cb_irqsafe + ieee80211_tx_status_irqsafe + ieee80211_unregister_hw + netlink_broadcast + netlink_register_notifier + netlink_unicast + netlink_unregister_notifier + net_namespace_list + nla_memcpy + param_ops_ushort + register_pernet_device + regulatory_hint + schedule_timeout_interruptible + skb_copy + skb_copy_expand + skb_dequeue + __skb_ext_put + skb_queue_tail + skb_unlink + unregister_pernet_device + wiphy_apply_custom_regulatory + +# required by md-mod.ko + ack_all_badblocks + alloc_page_buffers + _atomic_dec_and_lock + autoremove_wake_function + badblocks_clear + badblocks_exit + badblocks_init + badblocks_set + badblocks_show + badblocks_store + __bdevname + bdevname + bdev_read_only + bd_link_disk_holder + bd_unlink_disk_holder + bio_add_page + bio_associate_blkg + bio_endio + bio_put + bioset_exit + bioset_init + blk_alloc_queue + blkdev_get_by_dev + blkdev_put + blk_finish_plug + blk_queue_flag_clear + blk_queue_make_request + blk_queue_split + blk_register_region + blk_set_stacking_limits + blk_start_plug + blk_sync_queue + blk_unregister_region + bmap + check_disk_change + fget + file_path + flush_signals + free_buffer_head + int_pow + invalidate_bdev + invalidate_mapping_pages + kernel_sigaction + kernfs_find_and_get_ns + kernfs_notify + kernfs_put + kobject_get + kstrtobool + kstrtoll + kthread_create_on_node + kthread_parkme + kthread_should_park + kthread_should_stop + kthread_stop + mempool_create + mempool_destroy + mempool_kfree + mempool_kmalloc + percpu_ref_exit + percpu_ref_init + percpu_ref_switch_to_atomic_sync + percpu_ref_switch_to_percpu + prepare_to_wait + proc_create + proc_dointvec + register_reboot_notifier + register_sysctl_table + remove_proc_entry + seq_file_path + seq_lseek + seq_open + seq_read + seq_release + skip_spaces + strreplace + submit_bh + submit_bio_wait + sync_blockdev + sysfs_notify + unregister_reboot_notifier + unregister_sysctl_table + vfs_fsync + wake_up_process + +# required by nd_virtio.ko + bio_chain + bio_clone_blkg_association + +# required by net_failover.ko + dev_close + dev_get_stats + dev_mc_sync_multiple + dev_mc_unsync + dev_open + dev_uc_sync_multiple + dev_uc_unsync + netdev_change_features + netdev_lower_state_changed + netdev_pick_tx + pci_bus_type + +# required by psnap.ko + skb_pull_rcsum + +# required by rtc-test.ko + add_timer + device_init_wakeup + devm_rtc_allocate_device + __rtc_register_device + rtc_time64_to_tm + rtc_tm_to_time64 + rtc_update_irq + +# required by sdcardfs.ko + __break_lease + clear_inode + clear_nlink + configfs_register_subsystem + configfs_unregister_subsystem + config_group_init + config_group_init_type_name + config_item_init_type_name + copy_fs_struct + d_drop + dentry_open + dget_parent + d_invalidate + d_make_root + down_write + d_path + dput + d_rehash + d_set_d_op + d_splice_alias + filemap_write_and_wait + filp_close + filp_open + free_fs_struct + fscrypt_register_key_removal_notifier + fscrypt_unregister_key_removal_notifier + fs_parse + fsstack_copy_inode_size + generic_delete_inode + __generic_file_fsync + generic_file_llseek + generic_permission + generic_read_dir + iget5_locked + igrab + init_special_inode + inode_init_once + inode_newsize_ok + iput + iterate_dir + kern_path + kill_anon_super + lockref_get + lock_rename + lookup_one_len_unlocked + mntget + names_cachep + notify_change2 + override_creds + path_get + path_put + prepare_creds + __put_cred + register_filesystem + revert_creds + seq_puts + setattr_prepare + set_fs_pwd + set_nlink + shrink_dcache_sb + strcasecmp + strncasecmp + strrchr + touch_atime + truncate_inode_pages + truncate_setsize + unlock_new_inode + unlock_rename + unregister_filesystem + up_write + vfs_create2 + vfs_fsync_range + vfs_getattr + vfs_get_super + vfs_mkdir2 + vfs_path_lookup + vfs_read + vfs_rename2 + vfs_rmdir2 + vfs_statfs + vfs_unlink2 + vfs_write + +# required by snd-hda-codec-generic.ko + snd_ctl_boolean_stereo_info + strlcat + __sw_hweight32 + +# required by snd-hda-codec.ko + bpf_trace_run4 + current_work + device_attach + driver_register + driver_unregister + get_device_system_crosststamp + kvasprintf + ns_to_timespec + pm_runtime_allow + __pm_runtime_disable + pm_runtime_enable + pm_runtime_forbid + pm_runtime_force_resume + pm_runtime_force_suspend + __pm_runtime_idle + pm_runtime_set_autosuspend_delay + __pm_runtime_use_autosuspend + __printk_ratelimit + regcache_cache_only + regcache_mark_dirty + snd_card_rw_proc_new + snd_component_add + snd_ctl_add + _snd_ctl_add_slave + snd_ctl_add_vmaster_hook + snd_ctl_apply_vmaster_slaves + snd_ctl_boolean_mono_info + snd_ctl_find_id + snd_ctl_make_virtual_master + snd_ctl_new1 + snd_ctl_remove + snd_device_disconnect + snd_device_free + snd_jack_new + snd_jack_report + snd_jack_set_key + snd_pcm_hw_constraint_integer + snd_pcm_hw_constraint_minmax + snd_pcm_hw_constraint_step + snd_pcm_lib_default_mmap + snd_pcm_lib_free_pages + snd_pcm_lib_ioctl + snd_pcm_lib_malloc_pages + snd_pcm_lib_preallocate_pages_for_all + snd_pcm_limit_hw_rates + snd_pcm_new + snd_pcm_set_ops + snd_pcm_set_sync + snd_pcm_std_chmaps + strncat + timecounter_read + +# required by snd-hda-core.ko + add_uevent_var + bus_register + bus_unregister + device_add + device_del + device_initialize + krealloc + kstrtoint + pm_runtime_get_if_in_use + __pm_runtime_resume + __pm_runtime_set_status + regmap_exit + __regmap_init + regmap_read + regmap_write + snd_dma_alloc_pages + snd_dma_free_pages + snd_pcm_format_width + __sw_hweight64 + timecounter_init + +# required by snd-hda-intel.ko + bpf_trace_run1 + complete_all + param_array_ops + param_get_int + param_ops_bint + param_ops_charp + param_set_int + pci_dev_put + pci_disable_msi + pci_enable_msi + pci_get_device + pci_intx + pci_ioremap_bar + pci_read_config_word + pci_release_regions + pci_request_regions + pci_set_power_state + pci_write_config_byte + pci_write_config_dword + pci_write_config_word + snd_card_disconnect + snd_card_free + snd_card_new + +# required by test_meminit.ko + kmem_cache_alloc_bulk + kmem_cache_free_bulk + vfree + vmalloc + +# required by ttm.ko + clear_page + copy_page + dev_driver_string + devres_add + devres_alloc_node + devres_destroy + devres_free + dma_direct_map_page + dma_direct_unmap_page + dma_fence_enable_sw_signaling + dma_fence_signal + dma_resv_add_shared_fence + dma_resv_copy_fences + dma_resv_fini + dma_resv_init + dma_resv_reserve_shared + dma_resv_test_signaled_rcu + dma_resv_wait_timeout_rcu + drm_class_device_register + drm_class_device_unregister + drm_clflush_pages + drm_mm_init + drm_mm_insert_node_in_range + drm_mm_print + drm_mm_remove_node + drm_mm_takedown + drm_printf + __drm_printfn_debug + drm_vma_offset_add + drm_vma_offset_lookup_locked + drm_vma_offset_manager_destroy + drm_vma_offset_manager_init + drm_vma_offset_remove + mark_page_accessed + __memcpy_fromio + __memcpy_toio + __memset_io + mutex_is_locked + nr_swap_pages + _raw_read_lock + _raw_read_unlock + register_shrinker + reservation_ww_class + shmem_file_setup + shmem_read_mapping_page_gfp + si_mem_available + si_meminfo + unmap_mapping_range + unregister_shrinker + up_read + vmalloc_to_page + vmap + vmf_insert_mixed + vmf_insert_pfn + vm_get_page_prot + vunmap + ww_mutex_lock + +# required by veth.ko + bpf_redirect_info + __dev_forward_skb + nla_strlcpy + page_frag_free + __put_net + rtnl_configure_link + rtnl_create_link + rtnl_link_get_net + rtnl_nla_parse_ifla + skb_copy_header + skb_headers_offset_update + __tracepoint_xdp_bulk_tx + __xdp_release_frame + xdp_rxq_info_is_reg + +# required by virtio-gpu.ko + dma_direct_map_sg + dma_direct_sync_sg_for_device + dma_direct_unmap_sg + dma_fence_match_context + drm_add_edid_modes + drm_add_modes_noedid + drm_atomic_helper_check + drm_atomic_helper_cleanup_planes + drm_atomic_helper_commit + drm_atomic_helper_commit_hw_done + drm_atomic_helper_commit_modeset_disables + drm_atomic_helper_commit_modeset_enables + drm_atomic_helper_commit_planes + drm_atomic_helper_connector_destroy_state + drm_atomic_helper_connector_duplicate_state + drm_atomic_helper_connector_reset + drm_atomic_helper_crtc_destroy_state + drm_atomic_helper_crtc_duplicate_state + drm_atomic_helper_crtc_reset + drm_atomic_helper_dirtyfb + drm_atomic_helper_disable_plane + drm_atomic_helper_page_flip + drm_atomic_helper_plane_destroy_state + drm_atomic_helper_plane_duplicate_state + drm_atomic_helper_plane_reset + drm_atomic_helper_set_config + drm_atomic_helper_shutdown + drm_atomic_helper_update_plane + drm_atomic_helper_wait_for_vblanks + drm_compat_ioctl + drm_connector_attach_edid_property + drm_connector_attach_encoder + drm_connector_cleanup + drm_connector_init + drm_connector_register + drm_connector_unregister + drm_connector_update_edid_property + drm_crtc_cleanup + drm_crtc_init_with_planes + drm_crtc_send_vblank_event + drm_cvt_mode + drm_dbg + drm_dev_alloc + drm_dev_put + drm_dev_register + drm_dev_set_unique + drm_dev_unregister + drm_do_get_edid + drm_encoder_cleanup + drm_encoder_init + drm_err + drm_framebuffer_init + drm_gem_fb_create_handle + drm_gem_fb_destroy + drm_gem_handle_create + drm_gem_object_init + drm_gem_object_lookup + drm_gem_object_put_unlocked + drm_gem_object_release + drm_gem_prime_fd_to_handle + drm_gem_prime_handle_to_fd + drm_gem_prime_mmap + drm_helper_hpd_irq_event + drm_helper_mode_fill_fb_struct + drm_helper_probe_single_connector_modes + drm_ioctl + drm_kms_helper_hotplug_event + drm_mode_config_cleanup + drm_mode_config_init + drm_mode_config_reset + drm_mode_probed_add + drm_open + drm_plane_cleanup + drm_poll + drm_prime_pages_to_sg + drm_put_dev + drm_read + drm_release + drm_set_preferred_mode + drm_universal_plane_init + __get_task_comm + kmalloc_order_trace + memdup_user + noop_llseek + __sg_alloc_table_from_pages + sg_free_table + sg_next + sync_file_get_fence + __tracepoint_dma_fence_emit + +# required by virtio-rng.ko + hwrng_register + hwrng_unregister + wait_for_completion_killable + +# required by virtio_blk.ko + blk_execute_rq + blk_get_request + blk_mq_alloc_tag_set + blk_mq_complete_request + blk_mq_end_request + blk_mq_free_tag_set + blk_mq_init_queue + blk_mq_quiesce_queue + blk_mq_start_request + blk_mq_start_stopped_hw_queues + blk_mq_stop_hw_queue + blk_mq_unquiesce_queue + blk_mq_virtio_map_queues + blk_put_request + blk_queue_alignment_offset + blk_queue_io_min + blk_queue_io_opt + blk_queue_logical_block_size + blk_queue_max_discard_sectors + blk_queue_max_discard_segments + blk_queue_max_hw_sectors + blk_queue_max_segments + blk_queue_max_segment_size + blk_queue_max_write_zeroes_sectors + blk_queue_physical_block_size + blk_rq_map_kern + blk_rq_map_sg + blk_status_to_errno + _dev_notice + kobject_uevent_env + string_get_size + __sysfs_match_string + +# required by virtio_console.ko + cdev_add + cdev_alloc + cdev_del + device_destroy + fasync_helper + freezing_slow_path + hvc_alloc + hvc_instantiate + hvc_kick + hvc_poll + hvc_remove + __hvc_resize + kill_fasync + no_llseek + nonseekable_open + pipe_lock + pipe_unlock + __refrigerator + __register_chrdev + __splice_from_pipe + system_freezing_cnt + unlock_page + __unregister_chrdev + +# required by virtio_input.ko + input_alloc_absinfo + input_mt_init_slots + +# required by virtio_mmio.ko + device_for_each_child + device_register + __devm_request_region + iomem_resource + memparse + platform_device_register_full + +# required by virtio_net.ko + bpf_prog_add + bpf_prog_sub + __cpuhp_remove_state + __cpuhp_setup_state + __cpuhp_state_add_instance + __cpuhp_state_remove_instance + cpumask_next_wrap + cpus_read_lock + cpus_read_unlock + eth_commit_mac_addr_change + eth_prepare_mac_addr_change + flow_keys_basic_dissector + __napi_alloc_skb + napi_consume_skb + netdev_notify_peers + netdev_warn + netif_device_attach + netif_schedule_queue + netif_set_real_num_rx_queues + netif_set_real_num_tx_queues + __netif_set_xps_queue + __num_online_cpus + _raw_spin_trylock + skb_coalesce_rx_frag + __skb_flow_dissect + skb_page_frag_refill + skb_partial_csum_set + skb_to_sgvec + softnet_data + virtqueue_add_inbuf_ctx + virtqueue_enable_cb_delayed + virtqueue_enable_cb_prepare + virtqueue_get_buf_ctx + virtqueue_poll + +# required by virtio_pci.ko + irq_set_affinity_hint + pci_alloc_irq_vectors_affinity + pci_find_capability + pci_find_ext_capability + pci_find_next_capability + pci_free_irq_vectors + pci_iomap + pci_iomap_range + pci_irq_get_affinity + pci_irq_vector + pci_release_selected_regions + pci_request_selected_regions + virtio_device_freeze + virtio_device_restore + +# required by virtio_pmem.ko + nvdimm_bus_register + nvdimm_bus_unregister + nvdimm_pmem_region_create diff --git a/abi_gki_aarch64_hikey960_whitelist b/abi_gki_aarch64_hikey960_whitelist new file mode 100644 index 000000000000..6cd068e36759 --- /dev/null +++ b/abi_gki_aarch64_hikey960_whitelist @@ -0,0 +1,1550 @@ +[abi_whitelist] +# commonly used symbols + add_uevent_var + add_wait_queue + alloc_chrdev_region + __alloc_disk_node + __alloc_pages_nodemask + __alloc_skb + alloc_workqueue + amba_driver_register + amba_driver_unregister + amba_release_regions + amba_request_regions + __arch_copy_from_user + __arch_copy_to_user + arm64_const_caps_ready + blk_cleanup_queue + blk_execute_rq + blk_execute_rq_nowait + blk_get_queue + blk_mq_alloc_tag_set + blk_mq_complete_request + blk_mq_end_request + blk_mq_free_request + blk_mq_free_tag_set + blk_mq_init_queue + blk_mq_quiesce_queue + blk_mq_requeue_request + blk_mq_start_request + blk_mq_unquiesce_queue + blk_put_queue + blk_queue_flag_clear + blk_queue_flag_set + blk_queue_logical_block_size + blk_queue_max_discard_sectors + blk_queue_max_hw_sectors + blk_queue_max_segments + blk_queue_write_cache + blk_rq_map_sg + bpf_trace_run1 + bpf_trace_run2 + bpf_trace_run3 + bt_err + bt_info + bt_procfs_cleanup + bt_procfs_init + bt_sock_link + bt_sock_register + bt_sock_unlink + bt_sock_unregister + bus_register + bus_unregister + cancel_delayed_work + cancel_delayed_work_sync + cancel_work_sync + capable + cdev_device_add + cdev_device_del + cdev_init + __cfi_slowpath + __check_object_size + __class_create + class_destroy + clk_bulk_disable + clk_bulk_enable + clk_bulk_prepare + clk_bulk_unprepare + clk_disable + clk_enable + clk_get + clk_get_rate + clk_prepare + clk_put + clk_round_rate + clk_set_rate + clk_unprepare + complete + complete_all + __const_udelay + _copy_from_iter_full + cpu_hwcap_keys + cpu_hwcaps + cpu_number + __cpu_online_mask + __cpu_possible_mask + delayed_work_timer_fn + del_gendisk + del_timer + del_timer_sync + destroy_workqueue + dev_driver_string + _dev_err + dev_fwnode + device_add_disk + device_create + device_create_file + device_destroy + device_get_match_data + device_initialize + device_init_wakeup + device_property_present + device_property_read_string + device_property_read_u32_array + device_register + device_remove_file + device_set_wakeup_capable + device_unregister + device_wakeup_enable + _dev_info + devm_clk_get + devm_clk_get_optional + devm_gpiod_get + devm_gpiod_get_optional + devm_ioremap + devm_ioremap_resource + devm_kfree + devm_kmalloc + devm_pinctrl_get + __devm_regmap_init_i2c + __devm_regmap_init_mmio_clk + devm_regulator_register + devm_request_threaded_irq + devm_reset_control_array_get + __devm_reset_control_get + devm_thermal_zone_of_sensor_register + devm_usb_get_phy_by_phandle + dev_pm_opp_get_opp_count + devres_add + devres_alloc_node + devres_free + devres_release + dev_set_name + _dev_warn + disable_irq + disable_irq_nosync + dma_alloc_attrs + dma_direct_map_page + dma_direct_map_sg + dma_direct_sync_single_for_cpu + dma_direct_sync_single_for_device + dma_direct_unmap_page + dma_direct_unmap_sg + dma_free_attrs + dmam_alloc_attrs + dma_pool_alloc + dma_pool_create + dma_pool_destroy + dma_pool_free + dma_release_channel + dma_request_slave_channel + dma_set_coherent_mask + dma_set_mask + down_read + down_write + driver_unregister + drm_atomic_helper_connector_destroy_state + drm_atomic_helper_connector_duplicate_state + drm_atomic_helper_connector_reset + drm_connector_attach_encoder + drm_connector_cleanup + drm_connector_init + drm_connector_list_iter_begin + drm_connector_list_iter_end + drm_connector_list_iter_next + drm_connector_unregister + drm_err + drm_helper_probe_single_connector_modes + drm_mode_copy + drm_mode_vrefresh + enable_irq + event_triggers_call + extcon_get_edev_by_phandle + extcon_get_state + find_next_bit + find_next_zero_bit + finish_wait + flush_work + flush_workqueue + fput + free_irq + __free_pages + free_pages + fwnode_property_present + get_device + __get_free_pages + get_random_bytes + gpiod_set_value_cansleep + gpio_to_desc + hci_alloc_dev + hci_free_dev + hci_recv_frame + hci_register_dev + hci_unregister_dev + hrtimer_cancel + hrtimer_init + hrtimer_start_range_ns + i2c_del_driver + i2c_register_driver + i2c_transfer + ida_alloc_range + ida_destroy + ida_free + ieee80211_channel_to_frequency + ieee80211_connection_loss + ieee80211_find_sta + ieee80211_get_hdrlen_from_skb + ieee80211_queue_delayed_work + ieee80211_stop_rx_ba_session + init_net + init_timer_key + init_wait_entry + __init_waitqueue_head + input_event + input_register_device + __ioremap + iounmap + irq_get_irq_data + irq_of_parse_and_map + irq_set_irq_wake + jiffies + jiffies_to_msecs + kernel_sendmsg + kfree + kfree_const + kfree_skb + kimage_vaddr + __kmalloc + kmalloc_caches + kmalloc_order_trace + kmem_cache_alloc_trace + kmemdup + kstrtobool + kstrtoint + kstrtouint + kstrtoull + kthread_create_on_node + kthread_should_stop + kthread_stop + ktime_get + ktime_get_mono_fast_ns + ktime_get_with_offset + memchr_inv + memcpy + memdup_user + memmove + mempool_alloc + mempool_destroy + mempool_free + memset + mmc_add_host + mmc_alloc_host + mmc_detect_change + mmc_free_host + mmc_gpiod_request_cd + mmc_gpiod_request_ro + mmc_gpio_get_cd + mmc_gpio_get_ro + mmc_hw_reset + mmc_of_parse + mmc_regulator_get_supply + mmc_regulator_set_ocr + mmc_regulator_set_vqmmc + mmc_remove_host + mmc_request_done + mmc_send_tuning + mod_delayed_work_on + mod_timer + __module_get + module_layout + module_put + __msecs_to_jiffies + msleep + __mutex_init + mutex_lock + mutex_lock_interruptible + mutex_unlock + no_llseek + of_alias_get_id + of_clk_get + of_device_get_match_data + of_device_is_compatible + of_find_compatible_node + of_find_device_by_node + of_find_property + of_get_child_by_name + of_get_named_gpio_flags + of_get_property + of_graph_get_remote_node + of_graph_parse_endpoint + of_iomap + of_match_device + of_match_node + of_parse_phandle + of_platform_depopulate + of_platform_populate + of_property_read_string + of_property_read_string_helper + of_property_read_variable_u32_array + param_ops_bool + param_ops_charp + param_ops_int + param_ops_uint + pci_alloc_irq_vectors_affinity + pci_dev_put + pci_free_irq_vectors + pci_irq_vector + pci_match_id + pci_read_config_byte + pci_read_config_word + __pci_register_driver + pci_set_master + pci_set_mwi + pci_unregister_driver + perf_trace_buf_alloc + perf_trace_run_bpf_submit + pinctrl_lookup_state + pinctrl_pm_select_default_state + pinctrl_pm_select_sleep_state + pinctrl_select_state + platform_device_add + platform_device_add_properties + platform_device_add_resources + platform_device_alloc + platform_device_put + platform_device_unregister + __platform_driver_register + platform_driver_unregister + platform_get_irq + platform_get_irq_byname + platform_get_resource + platform_get_resource_byname + pm_runtime_allow + __pm_runtime_disable + pm_runtime_enable + pm_runtime_forbid + pm_runtime_force_resume + pm_runtime_force_suspend + __pm_runtime_idle + __pm_runtime_resume + pm_runtime_set_autosuspend_delay + __pm_runtime_set_status + __pm_runtime_suspend + __pm_runtime_use_autosuspend + pm_suspend_global_flags + pm_wakeup_dev_event + preempt_schedule + preempt_schedule_notrace + prepare_to_wait_event + printk + proto_register + proto_unregister + __pskb_pull_tail + put_device + put_disk + __put_task_struct + queue_delayed_work_on + queue_work_on + radix_tree_delete + ___ratelimit + _raw_spin_lock + _raw_spin_lock_bh + _raw_spin_lock_irq + _raw_spin_lock_irqsave + _raw_spin_unlock + _raw_spin_unlock_bh + _raw_spin_unlock_irq + _raw_spin_unlock_irqrestore + _raw_write_lock_bh + _raw_write_unlock_bh + __rcu_read_lock + __rcu_read_unlock + rdev_get_drvdata + refcount_dec_and_test_checked + refcount_inc_checked + refcount_inc_not_zero_checked + regmap_raw_read + regmap_raw_write + regmap_read + regmap_update_bits_base + regmap_write + regulator_disable + regulator_enable + regulator_enable_regmap + regulator_get_optional + regulator_get_voltage_sel_regmap + regulator_list_voltage_table + regulator_put + regulator_set_voltage + regulator_set_voltage_sel_regmap + release_firmware + remove_wait_queue + request_firmware + request_threaded_irq + reset_control_assert + reset_control_deassert + schedule + schedule_timeout + schedule_timeout_uninterruptible + scnprintf + sdio_claim_host + sdio_disable_func + sdio_enable_func + sdio_readsb + sdio_register_driver + sdio_release_host + sdio_unregister_driver + sdio_writesb + seq_printf + set_disk_ro + set_user_nice + sg_alloc_table + sg_free_table + sg_init_table + sg_miter_next + sg_miter_start + sg_miter_stop + sg_next + sg_pcopy_from_buffer + sg_pcopy_to_buffer + sk_alloc + skb_dequeue + skb_pull + skb_push + skb_put + skb_queue_head + skb_queue_purge + skb_queue_tail + sk_free + snprintf + sock_init_data + sock_no_mmap + sock_no_socketpair + __spi_register_driver + spi_setup + spi_sync + sprintf + sscanf + __stack_chk_fail + __stack_chk_guard + strcmp + strcpy + strlcpy + strlen + strncmp + strncpy + strnlen + strscpy + __sw_hweight32 + __sw_hweight64 + synchronize_irq + synchronize_rcu + syscon_node_to_regmap + syscon_regmap_lookup_by_phandle + sysfs_streq + system_wq + tasklet_init + __tasklet_schedule + trace_define_field + trace_event_buffer_commit + trace_event_buffer_reserve + trace_event_ignore_this_pid + trace_event_raw_init + trace_event_reg + trace_handle_return + trace_print_symbols_seq + trace_raw_output_prep + trace_seq_printf + trace_seq_putc + try_module_get + tty_termios_baud_rate + unregister_chrdev_region + up_read + up_write + usb_add_hcd + usb_amd_dev_put + usb_amd_quirk_pll_check + usb_amd_quirk_pll_disable + usb_amd_quirk_pll_enable + usb_calc_bus_time + usb_create_hcd + usb_disabled + usb_gadget_set_state + usb_get_dr_mode + usb_hcd_check_unlink_urb + usb_hcd_end_port_resume + usb_hcd_giveback_urb + usb_hc_died + usb_hcd_is_primary_hcd + usb_hcd_link_urb_to_ep + usb_hcd_pci_pm_ops + usb_hcd_pci_probe + usb_hcd_pci_remove + usb_hcd_pci_shutdown + usb_hcd_platform_shutdown + usb_hcd_poll_rh_status + usb_hcd_resume_root_hub + usb_hcds_loaded + usb_hcd_start_port_resume + usb_hcd_unlink_urb_from_ep + usb_hub_clear_tt_buffer + usb_put_hcd + usb_remove_hcd + usb_root_hub_lost_power + __usecs_to_jiffies + usleep_range + vfree + vmalloc + vmemmap + wait_for_completion + wait_for_completion_timeout + wait_woken + __wake_up + wake_up_process + __warn_printk + woken_wake_function + +# required by btsdio.ko + sdio_claim_irq + sdio_readb + sdio_release_irq + sdio_writeb + +# required by hci_uart.ko + baswap + bit_wait_timeout + bt_warn + __hci_cmd_sync + n_tty_ioctl_helper + nvmem_cell_get + nvmem_cell_put + nvmem_cell_read + out_of_line_wait_on_bit_timeout + __percpu_down_read + percpu_down_write + percpu_free_rwsem + __percpu_init_rwsem + __percpu_up_read + percpu_up_write + serdev_device_close + __serdev_device_driver_register + serdev_device_get_tiocm + serdev_device_open + serdev_device_set_baudrate + serdev_device_set_flow_control + serdev_device_set_tiocm + serdev_device_write_buf + serdev_device_write_flush + tty_driver_flush_buffer + tty_ldisc_flush + tty_register_ldisc + tty_set_termios + tty_termios_encode_baud_rate + tty_unregister_ldisc + tty_unthrottle + wake_up_bit + +# required by clk-hi655x.ko + devm_clk_hw_register + devm_of_clk_add_hw_provider + of_clk_hw_simple_get + +# required by cn.ko + netlink_broadcast + netlink_has_listeners + __netlink_kernel_create + netlink_kernel_release + netlink_unicast + __nlmsg_put + proc_create_single_data + remove_proc_entry + +# required by cpufreq-dt.ko + arch_set_freq_scale + cpufreq_enable_boost_support + cpufreq_freq_attr_scaling_available_freqs + cpufreq_freq_attr_scaling_boost_freqs + cpufreq_generic_frequency_table_verify + cpufreq_generic_get + cpufreq_generic_suspend + cpufreq_register_driver + cpufreq_unregister_driver + dev_pm_opp_free_cpufreq_table + dev_pm_opp_get_max_transition_latency + dev_pm_opp_get_sharing_cpus + dev_pm_opp_get_suspend_opp_freq + dev_pm_opp_init_cpufreq_table + dev_pm_opp_of_cpumask_add_table + dev_pm_opp_of_cpumask_remove_table + dev_pm_opp_of_get_sharing_cpus + dev_pm_opp_of_register_em + dev_pm_opp_put_regulators + dev_pm_opp_set_rate + dev_pm_opp_set_regulators + dev_pm_opp_set_sharing_cpus + get_cpu_device + policy_has_boost_freq + +# required by k3dma.ko + devm_free_irq + dma_async_device_register + dma_async_device_unregister + dma_async_tx_descriptor_init + dma_get_slave_channel + dmam_pool_create + of_dma_controller_free + of_dma_controller_register + tasklet_kill + +# required by adv7511.ko + devm_regulator_bulk_get + drm_add_edid_modes + drm_bridge_add + drm_bridge_remove + drm_connector_update_edid_property + drm_detect_hdmi_monitor + drm_do_get_edid + drm_kms_helper_hotplug_event + hdmi_avi_infoframe_init + hdmi_avi_infoframe_pack + i2c_new_ancillary_device + i2c_unregister_device + mipi_dsi_attach + mipi_dsi_detach + mipi_dsi_device_register_full + mipi_dsi_device_unregister + mipi_dsi_driver_register_full + mipi_dsi_driver_unregister + of_find_mipi_dsi_host_by_node + platform_device_register_full + regcache_mark_dirty + regcache_sync + regmap_bulk_write + regmap_register_patch + regulator_bulk_disable + regulator_bulk_enable + +# required by kirin-drm.ko + component_bind_all + component_master_add_with_match + component_master_del + component_unbind_all + drm_atomic_get_crtc_state + drm_atomic_helper_check + drm_atomic_helper_commit + drm_atomic_helper_crtc_destroy_state + drm_atomic_helper_crtc_duplicate_state + drm_atomic_helper_crtc_reset + drm_atomic_helper_disable_plane + drm_atomic_helper_page_flip + drm_atomic_helper_plane_destroy_state + drm_atomic_helper_plane_duplicate_state + drm_atomic_helper_plane_reset + drm_atomic_helper_set_config + drm_atomic_helper_update_plane + drm_compat_ioctl + drm_connector_register + drm_crtc_arm_vblank_event + drm_crtc_cleanup + drm_crtc_handle_vblank + drm_crtc_init_with_planes + drm_crtc_send_vblank_event + drm_crtc_vblank_get + drm_crtc_vblank_off + drm_crtc_vblank_on + drm_dev_alloc + drm_dev_put + drm_dev_register + drm_dev_unregister + drm_fb_cma_get_gem_obj + drm_gem_cma_dumb_create_internal + drm_gem_cma_free_object + drm_gem_cma_mmap + drm_gem_cma_prime_get_sg_table + drm_gem_cma_prime_import_sg_table + drm_gem_cma_prime_mmap + drm_gem_cma_prime_vmap + drm_gem_cma_prime_vunmap + drm_gem_cma_vm_ops + drm_gem_fb_create + drm_gem_prime_export + drm_gem_prime_fd_to_handle + drm_gem_prime_handle_to_fd + drm_gem_prime_import + drm_ioctl + drm_kms_helper_poll_fini + drm_kms_helper_poll_init + drm_mode_config_cleanup + drm_mode_config_init + drm_mode_config_reset + drm_of_component_match_add + drm_open + drm_plane_cleanup + drm_poll + drm_read + drm_release + drm_universal_plane_init + drm_vblank_init + noop_llseek + +# required by kirin-dsi.ko + component_add + component_del + drm_bridge_attach + drm_dbg + drm_encoder_cleanup + drm_encoder_init + drm_of_find_possible_crtcs + drm_panel_attach + drm_panel_disable + drm_panel_enable + drm_panel_get_modes + drm_panel_prepare + drm_panel_unprepare + drm_sysfs_hotplug_event + mipi_dsi_host_register + mipi_dsi_host_unregister + of_drm_find_bridge + of_drm_find_panel + of_graph_get_next_endpoint + of_graph_get_remote_port_parent + +# required by hwmon.ko + __class_register + class_unregister + kstrtoll + strpbrk + +# required by i2c-designware-core.ko + i2c_add_numbered_adapter + i2c_generic_scl_recovery + i2c_recover_bus + +# required by i2c-designware-platform.ko + i2c_del_adapter + i2c_parse_fw_timings + +# required by i2c-dev.ko + bus_register_notifier + bus_unregister_notifier + cdev_add + cdev_del + device_for_each_child + i2c_adapter_type + i2c_bus_type + i2c_for_each_dev + i2c_get_adapter + i2c_put_adapter + i2c_smbus_xfer + i2c_transfer_buffer_flags + i2c_verify_client + register_chrdev_region + +# required by hisi_powerkey.ko + devm_input_allocate_device + devm_request_any_context_irq + input_set_capability + +# required by ambakmi.ko + serio_interrupt + serio_reconnect + __serio_register_port + serio_unregister_port + +# required by hi3660-mailbox.ko + devm_mbox_controller_register + +# required by cec.ko + kobject_set_name + wait_for_completion_killable + +# required by hi6421-pmic-core.ko + devm_mfd_add_devices + +# required by hi655x-pmic.ko + devm_gpio_request_one + gpiod_to_irq + mfd_add_devices + mfd_remove_devices + regmap_add_irq_chip + regmap_del_irq_chip + regmap_irq_get_domain + +# required by mmc_block.ko + blk_get_request + __blk_mq_end_request + blk_mq_run_hw_queues + blk_put_request + blk_queue_bounce_limit + blk_queue_can_use_dma_map_merging + blk_queue_max_segment_size + blk_queue_rq_timeout + blk_update_request + check_disk_change + dma_get_merge_boundary + mmc_app_cmd + mmc_calc_max_discard + mmc_can_erase + mmc_can_sanitize + mmc_can_secure_erase_trim + mmc_can_trim + __mmc_claim_host + mmc_cmdq_disable + mmc_cmdq_enable + mmc_cqe_post_req + mmc_cqe_recovery + mmc_cqe_start_req + mmc_detect_card_removed + mmc_erase + mmc_erase_group_aligned + mmc_flush_cache + mmc_get_card + mmc_get_ext_csd + mmc_put_card + mmc_register_driver + mmc_release_host + mmc_retune_pause + mmc_retune_release + mmc_retune_unpause + mmc_run_bkops + __mmc_send_status + mmc_send_status + mmc_set_data_timeout + mmc_start_request + mmc_switch + mmc_unregister_driver + mmc_wait_for_cmd + mmc_wait_for_req + nonseekable_open + register_blkdev + sg_init_one + simple_strtoul + string_get_size + unregister_blkdev + +# required by dw_mmc.ko + device_property_read_string_array + dma_direct_sync_sg_for_cpu + dma_direct_sync_sg_for_device + mmc_can_gpio_cd + sdio_signal_irq + +# required by mmc_spi.ko + mmc_gpiod_request_cd_irq + spi_bus_lock + spi_bus_unlock + spi_sync_locked + +# required by of_mmc_spi.ko + mmc_of_parse_voltage + +# required by wl18xx.ko + __cfg80211_alloc_event_skb + __cfg80211_send_event_skb + ieee80211_radar_detected + nla_put + +# required by wlcore.ko + bcmp + cfg80211_find_elem_match + cfg80211_find_vendor_elem + consume_skb + device_create_bin_file + device_remove_bin_file + dev_pm_clear_wake_irq + dev_pm_set_dedicated_wake_irq + get_random_u32 + get_zeroed_page + ieee80211_alloc_hw_nm + ieee80211_ap_probereq_get + ieee80211_beacon_get_tim + ieee80211_chswitch_done + ieee80211_cqm_beacon_loss_notify + ieee80211_cqm_rssi_notify + ieee80211_csa_finish + ieee80211_free_hw + ieee80211_free_txskb + ieee80211_frequency_to_channel + ieee80211_hdrlen + ieee80211_iterate_active_interfaces_atomic + ieee80211_iterate_interfaces + ieee80211_nullfunc_get + ieee80211_probereq_get + ieee80211_proberesp_get + ieee80211_pspoll_get + ieee80211_queue_work + ieee80211_ready_on_channel + ieee80211_register_hw + ieee80211_remain_on_channel_expired + ieee80211_report_low_ack + ieee80211_restart_hw + ieee80211_rx_napi + ieee80211_scan_completed + ieee80211_sched_scan_results + ieee80211_sched_scan_stopped + ieee80211_sta_ps_transition + ieee80211_stop_queue + ieee80211_stop_queues + ieee80211_tx_status + ieee80211_unregister_hw + ieee80211_wake_queue + ieee80211_wake_queues + jiffies_to_usecs + __local_bh_enable_ip + __netdev_alloc_skb + __nla_parse + request_firmware_nowait + rfc1042_header + simple_read_from_buffer + skb_trim + vscnprintf + wiphy_to_ieee80211_hw + +# required by wlcore_sdio.ko + platform_device_add_data + print_hex_dump + sdio_f0_readb + sdio_f0_writeb + sdio_get_host_pm_caps + sdio_memcpy_fromio + sdio_memcpy_toio + sdio_set_block_size + sdio_set_host_pm_flags + +# required by nvme-core.ko + blk_freeze_queue_start + blk_mq_alloc_request + blk_mq_alloc_request_hctx + blk_mq_delay_kick_requeue_list + blk_mq_freeze_queue + blk_mq_freeze_queue_wait + blk_mq_freeze_queue_wait_timeout + blk_mq_request_completed + blk_mq_unfreeze_queue + blk_mq_unique_tag + blk_poll + blk_queue_chunk_sectors + blk_queue_flag_test_and_set + blk_queue_io_min + blk_queue_io_opt + blk_queue_max_discard_segments + blk_queue_max_write_zeroes_sectors + blk_queue_physical_block_size + blk_queue_virt_boundary + blk_rq_map_kern + blk_rq_map_user + blk_rq_unmap_user + blk_set_queue_dying + blk_status_to_errno + blk_sync_queue + cleanup_srcu_struct + completion_done + device_add + device_del + device_remove_file_self + dev_pm_qos_expose_latency_tolerance + dev_pm_qos_hide_latency_tolerance + dev_pm_qos_update_user_latency_tolerance + __init_rwsem + init_srcu_struct + kasprintf + kobject_uevent_env + list_sort + param_ops_byte + param_ops_ulong + revalidate_disk + synchronize_srcu + sysfs_create_link + sysfs_remove_link + uuid_null + +# required by nvme.ko + async_schedule_node + blk_mq_map_queues + blk_mq_pci_map_queues + blk_mq_tagset_busy_iter + blk_mq_tagset_wait_completed_request + blk_mq_tag_to_rq + blk_mq_update_nr_hw_queues + device_release_driver + dma_max_mapping_size + __do_once_done + __do_once_start + mempool_create_node + mempool_kfree + mempool_kmalloc + param_get_int + param_set_int + pci_device_is_present + pci_disable_device + pcie_aspm_enabled + pci_enable_device_mem + pci_free_irq + pci_load_saved_state + pci_release_selected_regions + pci_request_irq + pci_request_selected_regions + pci_restore_state + pci_save_state + pci_select_bars + sysfs_remove_file_from_group + wait_for_completion_io_timeout + +# required by nvmet.ko + bin2hex + bio_add_page + bio_alloc_bioset + bio_associate_blkg + bio_chain + bio_endio + bio_init + bio_put + blkdev_get_by_path + __blkdev_issue_discard + blkdev_issue_flush + __blkdev_issue_zeroout + blkdev_put + configfs_register_subsystem + configfs_unregister_subsystem + config_group_init + config_group_init_type_name + cpumask_next + _ctype + filp_open + fs_bio_set + hex_to_bin + iov_iter_bvec + kmem_cache_create + kmem_cache_destroy + kstrndup + kstrtou16 + mempool_alloc_slab + mempool_create + mempool_free_slab + nr_cpu_ids + __per_cpu_offset + percpu_ref_exit + percpu_ref_init + percpu_ref_kill_and_confirm + radix_tree_next_chunk + __request_module + sgl_alloc + sgl_free + sg_zero_buffer + strcspn + submit_bio + uuid_gen + uuid_parse + vfs_fallocate + vfs_fsync + vfs_getattr + +# required by phy-hi3660-usb3.ko + __devm_of_phy_provider_register + devm_phy_create + of_phy_simple_xlate + +# required by reboot-mode.ko + kstrdup_const + register_reboot_notifier + unregister_reboot_notifier + +# required by hi6421v530-regulator.ko + regulator_disable_regmap + regulator_is_enabled_regmap + regulator_map_voltage_ascend + +# required by hi655x-regulator.ko + regulator_list_voltage_linear + +# required by rtc-efi.ko + devm_rtc_device_register + efi + __platform_driver_probe + rtc_valid_tm + rtc_year_days + seq_puts + +# required by ufs-hisi.ko + devm_platform_ioremap_resource + ufshcd_dme_get_attr + ufshcd_dme_set_attr + ufshcd_get_pwr_dev_param + ufshcd_pltfrm_init + ufshcd_pltfrm_resume + ufshcd_pltfrm_runtime_idle + ufshcd_pltfrm_runtime_resume + ufshcd_pltfrm_runtime_suspend + ufshcd_pltfrm_shutdown + ufshcd_pltfrm_suspend + ufshcd_remove + +# required by spi-pl022.ko + devm_gpio_request + devm_spi_register_controller + dma_request_chan + __dma_request_channel + gpiod_direction_output_raw + gpiod_set_raw_value + loops_per_jiffy + pinctrl_pm_select_idle_state + __spi_alloc_controller + spi_controller_resume + spi_controller_suspend + spi_finalize_current_message + spi_get_next_queued_message + __udelay + +# required by spidev.ko + __register_chrdev + stream_open + __unregister_chrdev + +# required by ion_cma_heap.ko + cma_alloc + cma_for_each_area + cma_get_name + cma_release + ion_buffer_prep_noncached + __ion_device_add_heap + ion_device_remove_heap + +# required by hisi_thermal.ko + _dev_crit + of_thermal_get_ntrips + of_thermal_get_trip_points + thermal_zone_device_update + +# required by 8250_dw.ko + dw8250_setup_port + of_device_is_big_endian + serial8250_clear_and_reinit_fifos + serial8250_do_pm + serial8250_do_set_ldisc + serial8250_do_set_termios + serial8250_handle_irq + serial8250_register_8250_port + serial8250_resume_port + serial8250_suspend_port + serial8250_unregister_port + +# required by dwc3-haps.ko + pcim_enable_device + +# required by dwc3-of-simple.ko + clk_bulk_get_all + clk_bulk_put_all + of_reset_control_array_get + reset_control_put + reset_control_reset + +# required by dwc3-qcom.ko + devm_extcon_register_notifier + irq_modify_status + of_clk_get_parent_count + +# required by dwc3.ko + bpf_trace_run4 + device_property_read_u8_array + devm_clk_bulk_get_all + devm_phy_get + devm_usb_get_phy + extcon_find_edev_by_node + extcon_get_extcon_dev + extcon_register_notifier + extcon_unregister_notifier + of_usb_get_phy_mode + phy_exit + phy_init + phy_pm_runtime_get_sync + phy_pm_runtime_put_sync + phy_power_off + phy_power_on + phy_set_mode_ext + platform_get_irq_byname_optional + system_freezable_wq + usb_add_gadget_udc + usb_decode_ctrl + usb_del_gadget_udc + usb_ep_set_maxpacket_limit + usb_gadget_giveback_request + usb_gadget_map_request_by_dev + usb_gadget_udc_reset + usb_gadget_unmap_request_by_dev + usb_get_maximum_speed + +# required by gadgetfs.ko + _copy_to_iter + current_time + d_add + d_alloc_name + d_delete + d_make_root + dput + dup_iter + fasync_helper + generic_delete_inode + get_next_ino + get_tree_single + kill_fasync + kill_litter_super + kiocb_set_cancel_fn + mutex_trylock + new_inode + register_filesystem + simple_dir_inode_operations + simple_dir_operations + simple_statfs + unregister_filesystem + unuse_mm + usb_ep_alloc_request + usb_ep_clear_halt + usb_ep_dequeue + usb_ep_disable + usb_ep_enable + usb_ep_fifo_flush + usb_ep_fifo_status + usb_ep_free_request + usb_ep_queue + usb_ep_set_halt + usb_gadget_probe_driver + usb_gadget_unregister_driver + usb_gadget_vbus_draw + usb_get_gadget_udc_name + use_mm + +# required by ehci-hcd.ko + ehci_cf_port_reset_rwsem + usb_for_each_dev + +# required by ehci-pci.ko + pci_clear_mwi + pci_find_capability + pci_read_config_dword + pci_write_config_byte + usb_amd_hang_symptom_quirk + +# required by ehci-platform.ko + device_pm_wait_for_dev + usb_of_get_companion_dev + +# required by ohci-hcd.ko + gen_pool_dma_alloc_align + gen_pool_dma_zalloc_align + gen_pool_free_owner + sb800_prefetch + +# required by ohci-pci.ko + pci_get_slot + usb_amd_prefetch_quirk + +# required by xhci-hcd.ko + add_timer + devm_add_action + __num_online_cpus + param_ops_ullong + radix_tree_insert + radix_tree_lookup + radix_tree_maybe_preload + usb_amd_pt_check_port + usb_asmedia_modifyflowcontrol + usb_disable_xhci_ports + usb_hcd_irq + usb_hcd_map_urb_for_dma + usb_wakeup_notification + vsnprintf + +# required by xhci-pci.ko + pci_d3cold_disable + pci_set_power_state + usb_create_shared_hcd + usb_enable_intel_xhci_ports + +# required by xhci-plat-hcd.ko + of_fwnode_ops + of_usb_host_tpl_support + pci_bus_type + __usb_create_hcd + +# required by roles.ko + class_find_device + device_connection_find_match + device_match_fwnode + device_match_name + fwnode_connection_find_match + fwnode_get_parent + __sysfs_match_string + +# required by tcpci.ko + device_get_named_child_node + +# required by tcpci_rt1711h.ko + i2c_smbus_read_word_data + +# required by tcpm.ko + devm_power_supply_register + fwnode_property_read_string + fwnode_property_read_u32_array + power_supply_changed + power_supply_get_drvdata + typec_altmode_attention + typec_altmode_notify + typec_altmode_update_active + typec_altmode_vdm + typec_find_port_data_role + typec_find_port_power_role + typec_find_power_role + typec_match_altmode + typec_partner_register_altmode + typec_partner_set_identity + typec_port_register_altmode + typec_register_partner + typec_register_port + typec_set_data_role + typec_set_mode + typec_set_orientation + typec_set_pwr_opmode + typec_set_pwr_role + typec_set_vconn_role + typec_unregister_altmode + typec_unregister_partner + typec_unregister_port + +# required by hidp.ko + hid_add_device + hid_allocate_device + hid_destroy_device + hid_ignore + hid_input_report + hid_parse_report + input_allocate_device + input_unregister_device + l2cap_conn_get + l2cap_conn_put + l2cap_is_socket + l2cap_register_user + l2cap_unregister_user + memscan + __module_put_and_exit + sockfd_lookup + sock_no_accept + sock_no_bind + sock_no_connect + sock_no_getname + sock_no_getsockopt + sock_no_listen + sock_no_recvmsg + sock_no_sendmsg + sock_no_setsockopt + sock_no_shutdown + +# required by rfcomm.ko + add_wait_queue_exclusive + bt_accept_dequeue + bt_accept_enqueue + bt_accept_unlink + bt_sock_ioctl + bt_sock_poll + bt_sock_reclassify_lock + bt_sock_stream_recvmsg + bt_sock_wait_ready + bt_sock_wait_state + device_move + hci_conn_check_secure + hci_conn_security + hci_conn_switch_role + hci_get_route + hci_register_cb + hci_unregister_cb + kernel_accept + kernel_bind + kernel_connect + kernel_listen + lock_sock_nested + put_tty_driver + _raw_read_lock + _raw_read_unlock + _raw_write_lock + _raw_write_unlock + release_sock + security_sk_clone + sock_alloc_send_skb + sock_create_kern + sock_gettstamp + sock_release + __tty_alloc_driver + tty_flip_buffer_push + tty_insert_flip_string_fixed_flag + tty_kref_put + tty_port_close + tty_port_hangup + tty_port_init + tty_port_install + tty_port_open + tty_port_put + tty_port_register_device + tty_port_tty_get + tty_port_tty_hangup + tty_port_tty_wakeup + tty_register_driver + tty_set_operations + tty_std_termios + tty_unregister_device + tty_unregister_driver + tty_vhangup + tty_wakeup + +# required by rfkill-gpio.ko + rfkill_alloc + rfkill_destroy + rfkill_find_type + rfkill_register + rfkill_unregister + +# required by snd-soc-hdmi-codec.ko + devm_snd_soc_register_component + hdmi_audio_infoframe_init + snd_ctl_add + snd_ctl_new1 + snd_pcm_add_chmap_ctls + snd_pcm_create_iec958_consumer_hw_params + snd_pcm_format_width + snd_pcm_hw_constraint_eld + snd_soc_dapm_add_routes + snd_soc_jack_report + +# required by snd-soc-simple-card-utils.ko + devm_get_clk_from_child + devm_kasprintf + devm_kvasprintf + snd_soc_card_jack_new + snd_soc_dai_set_sysclk + snd_soc_dai_set_tdm_slot + snd_soc_dapm_get_pin_switch + snd_soc_dapm_info_pin_switch + snd_soc_dapm_put_pin_switch + snd_soc_jack_add_gpios + snd_soc_of_parse_audio_routing + snd_soc_of_parse_audio_simple_widgets + snd_soc_of_parse_card_name + snd_soc_of_parse_daifmt + +# required by snd-soc-simple-card.ko + devm_snd_soc_register_card + of_device_is_available + of_get_next_child + of_get_parent + of_parse_phandle_with_args + snd_soc_of_get_dai_name + snd_soc_of_parse_node_prefix + snd_soc_of_parse_tdm_slot + snd_soc_pm_ops + +# required by hi3660-i2s.ko + devm_snd_dmaengine_pcm_register + pinctrl_put + snd_dmaengine_pcm_prepare_slave_config + snd_soc_register_component + snd_soc_unregister_component + +# required by mali_kbase.ko + anon_inode_getfd + __bitmap_weight + cache_line_size + clear_page + __close_fd + devfreq_add_device + devfreq_cooling_unregister + devfreq_recommended_opp + devfreq_register_opp_notifier + devfreq_remove_device + devfreq_resume_device + devfreq_suspend_device + devfreq_unregister_opp_notifier + dev_pm_opp_find_freq_floor + dev_pm_opp_get_voltage + dev_pm_opp_of_add_table + dev_pm_opp_of_remove_table + dev_pm_opp_put + dma_buf_attach + dma_buf_begin_cpu_access + dma_buf_detach + dma_buf_end_cpu_access + dma_buf_get + dma_buf_kmap + dma_buf_kunmap + dma_buf_map_attachment + dma_buf_mmap + dma_buf_put + dma_buf_unmap_attachment + dma_fence_add_callback + dma_fence_context_alloc + dma_fence_default_wait + dma_fence_get_status + dma_fence_init + dma_fence_release + dma_fence_remove_callback + dma_fence_signal + down + downgrade_write + down_trylock + dump_stack + fd_install + find_vma + get_unused_fd_flags + get_user_pages + get_user_pages_fast + get_user_pages_remote + iomem_resource + kimage_voffset + ktime_add_safe + ktime_get_raw_ts64 + misc_deregister + misc_register + __mmdrop + mm_trace_rss_stat + msleep_interruptible + of_devfreq_cooling_register_power + of_get_next_available_child + of_property_read_u64 + physvirt_offset + __put_page + rb_erase + rb_first + rb_insert_color + rb_next + rb_prev + rb_replace_node + register_shrinker + __release_region + remap_pfn_range + remap_vmalloc_range + __request_region + set_page_dirty_lock + sync_file_create + sync_file_get_fence + sysfs_create_group + sysfs_remove_group + thermal_zone_get_temp + thermal_zone_get_zone_by_name + _totalram_pages + unmap_mapping_range + unregister_shrinker + up + vabits_actual + vmalloc_user + vmap + vmf_insert_pfn + vm_mmap + vunmap + vzalloc diff --git a/abi_gki_aarch64_qcom_whitelist b/abi_gki_aarch64_qcom_whitelist index b9e1c5a74a21..5e15b6ce932d 100644 --- a/abi_gki_aarch64_qcom_whitelist +++ b/abi_gki_aarch64_qcom_whitelist @@ -495,6 +495,7 @@ dev_remove_pack devres_add __devres_alloc_node + devres_alloc_node devres_destroy devres_free devres_release @@ -937,6 +938,20 @@ get_cpu_device get_device __get_free_pages + gether_cleanup + gether_connect + gether_disconnect + gether_get_dev_addr + gether_get_host_addr + gether_get_host_addr_cdc + gether_get_ifname + gether_get_qmult + gether_register_netdev + gether_set_dev_addr + gether_set_gadget + gether_set_host_addr + gether_set_qmult + gether_setup_name_default get_next_ino get_option get_random_bytes @@ -1268,6 +1283,8 @@ led_trigger_register_simple led_trigger_unregister led_trigger_unregister_simple + __list_add_valid + __list_del_entry_valid list_sort llist_add_batch llist_reverse_order @@ -1824,6 +1841,7 @@ register_pm_notifier register_reboot_notifier register_restart_handler + __register_rpmsg_driver register_shrinker register_syscore_ops register_sysctl_table @@ -1892,6 +1910,17 @@ rfkill_init_sw_state rfkill_register rfkill_unregister + rndis_deregister + rndis_free_response + rndis_get_next_response + rndis_msg_parser + rndis_register + rndis_set_host_mac + rndis_set_param_dev + rndis_set_param_medium + rndis_set_param_vendor + rndis_signal_connect + rndis_uninit round_jiffies rpmh_flush rpmh_invalidate @@ -1899,6 +1928,15 @@ rpmh_write rpmh_write_async rpmh_write_batch + rpmsg_create_ept + rpmsg_destroy_ept + rpmsg_get_sigs + rpmsg_poll + rpmsg_register_device + rpmsg_send + rpmsg_set_sigs + rpmsg_trysend + rpmsg_unregister_device rtc_class_close rtc_class_open rtc_read_time @@ -2322,6 +2360,19 @@ tty_flip_buffer_push __tty_insert_flip_char tty_insert_flip_string_fixed_flag + typec_altmode_get_partner + typec_altmode_update_active + typec_get_drvdata + typec_partner_register_altmode + typec_port_register_altmode + typec_register_partner + typec_register_port + typec_set_data_role + typec_set_pwr_opmode + typec_set_pwr_role + typec_unregister_altmode + typec_unregister_partner + typec_unregister_port uart_add_one_port uart_console_device uart_console_write @@ -2383,6 +2434,7 @@ unregister_pernet_subsys unregister_pm_notifier unregister_reboot_notifier + unregister_rpmsg_driver unregister_shrinker unregister_syscore_ops unregister_sysctl_table @@ -2470,6 +2522,7 @@ usb_hcd_pci_probe usb_hcd_pci_remove usb_hcd_pci_shutdown + usb_hcd_platform_shutdown usb_hcd_poll_rh_status usb_hcd_resume_root_hub usb_hcd_start_port_resume diff --git a/abi_gki_aarch64_unisoc_whitelist b/abi_gki_aarch64_unisoc_whitelist index fba0edb4a020..1ec428eac6c0 100644 --- a/abi_gki_aarch64_unisoc_whitelist +++ b/abi_gki_aarch64_unisoc_whitelist @@ -31,6 +31,8 @@ cancel_work_sync cdev_add cdev_del + cdev_device_add + cdev_device_del cdev_init __cfi_slowpath __check_object_size @@ -52,6 +54,7 @@ clk_unprepare complete complete_all + config_ep_by_speed __const_udelay cpu_hwcap_keys cpu_hwcaps @@ -61,7 +64,6 @@ __cpu_possible_mask csum_ipv6_magic csum_partial - debug_smp_processor_id default_llseek delayed_work_timer_fn del_timer @@ -85,15 +87,19 @@ device_property_read_u32_array device_register device_remove_file + device_set_wakeup_capable device_unregister _dev_info __dev_kfree_skb_any devm_add_action devm_backlight_device_register + devm_clk_bulk_get_all devm_clk_get devm_free_irq + devm_gpiochip_add_data devm_gpiod_get devm_gpio_request + devm_hwspin_lock_request_specific __devm_iio_device_register devm_ioremap_nocache devm_ioremap_resource @@ -101,6 +107,7 @@ devm_kmalloc devm_kmemdup devm_mfd_add_devices + devm_nvmem_register devm_pinctrl_get devm_power_supply_register __devm_regmap_init @@ -109,6 +116,9 @@ devm_regulator_get devm_regulator_register devm_request_threaded_irq + devm_spi_register_controller + devm_usb_get_phy + devm_usb_get_phy_by_phandle dev_queue_xmit dev_set_name _dev_warn @@ -158,26 +168,35 @@ __free_pages free_pages_exact free_percpu + free_reserved_area freezing_slow_path fwnode_property_present fwnode_property_read_string generic_file_llseek + generic_handle_irq genl_register_family genl_unregister_family gen_pool_add_owner gen_pool_alloc_algo_owner gen_pool_create gen_pool_free_owner + get_cpu_device __get_free_pages get_random_bytes + gpiochip_get_data + gpiochip_line_is_irq gpiod_direction_input gpiod_direction_output_raw gpiod_get_raw_value gpiod_set_raw_value + gpiod_to_chip gpiod_to_irq gpio_free gpio_request gpio_to_desc + handle_bad_irq + handle_edge_irq + handle_level_irq i2c_del_driver i2c_register_driver i2c_smbus_read_byte_data @@ -202,6 +221,7 @@ __ioremap iounmap ip_route_output_flow + irq_find_mapping irq_get_irq_data irq_modify_status irq_of_parse_and_map @@ -210,7 +230,6 @@ jiffies jiffies_to_msecs kernel_kobj - kernel_read __kfifo_alloc __kfifo_free __kfifo_in @@ -230,6 +249,7 @@ kmemdup kobject_create_and_add kobject_uevent_env + kstrndup kstrtobool kstrtoint kstrtoll @@ -253,6 +273,7 @@ msleep __mutex_init mutex_lock + mutex_lock_interruptible mutex_trylock mutex_unlock nd_tbl @@ -281,11 +302,13 @@ of_find_property of_get_child_by_name of_get_named_gpio_flags + of_get_next_available_child of_get_next_child of_get_property of_get_regulator_init_data of_graph_get_remote_node of_match_node + of_nvmem_cell_get of_parse_phandle of_parse_phandle_with_args of_platform_depopulate @@ -294,6 +317,7 @@ of_property_match_string of_property_read_string of_property_read_u32_index + of_property_read_u64 of_property_read_variable_u32_array of_prop_next_string panic @@ -330,6 +354,8 @@ pm_runtime_allow __pm_runtime_disable pm_runtime_enable + pm_runtime_force_resume + pm_runtime_force_suspend pm_runtime_forbid __pm_runtime_idle __pm_runtime_resume @@ -345,8 +371,6 @@ power_supply_get_drvdata power_supply_get_property power_supply_put - preempt_count_add - preempt_count_sub preempt_schedule preempt_schedule_notrace prepare_to_wait_event @@ -449,6 +473,7 @@ snd_soc_register_component snd_soc_unregister_component snprintf + __spi_alloc_controller sprintf sscanf __stack_chk_fail @@ -466,6 +491,8 @@ strncpy_from_user strnlen strstr + __sw_hweight32 + __sw_hweight64 syscon_regmap_lookup_by_phandle syscon_regmap_lookup_by_phandle_args sysfs_create_file_ns @@ -485,6 +512,7 @@ tasklet_init tasklet_kill __tasklet_schedule + thermal_zone_get_zone_by_name trace_define_field trace_event_buffer_commit trace_event_buffer_reserve @@ -530,15 +558,28 @@ usb_control_msg usb_del_gadget_udc usb_deregister + usb_ep_alloc_request + usb_ep_autoconfig + usb_ep_dequeue + usb_ep_enable + usb_ep_free_request + usb_ep_queue usb_ep_set_maxpacket_limit usb_find_common_endpoints usb_free_coherent usb_free_urb + usb_function_register + usb_function_unregister usb_gadget_giveback_request usb_gadget_udc_reset usb_get_dr_mode usb_get_intf + usb_hcd_is_primary_hcd + usb_interface_id usb_kill_urb + usb_phy_get_charger_current + usb_phy_set_charger_current + usb_put_function_instance usb_put_intf usb_register_driver usb_submit_urb @@ -550,6 +591,7 @@ vm_map_ram vm_unmap_ram vsnprintf + vunmap wait_for_completion wait_for_completion_interruptible wait_for_completion_interruptible_timeout @@ -583,9 +625,21 @@ usb_get_from_anchor usb_ifnum_to_if +# required by charger-manager.ko + alarm_cancel + alarm_expires_remaining + alarm_init + alarm_start + alarmtimer_get_rtcdev + devm_kasprintf + regulator_force_disable + regulator_set_current_limit + thermal_zone_get_temp + # required by clk-sprd.ko clk_hw_get_num_parents clk_hw_get_parent + clk_hw_is_enabled __clk_mux_determine_rate devm_clk_hw_register devm_of_clk_add_hw_provider @@ -650,6 +704,15 @@ of_property_read_variable_u8_array request_firmware_nowait +# required by gpio-eic-sprd.ko + gpiochip_find + +# required by gpio-pmic-eic-sprd.ko + handle_nested_irq + +# required by gpio-sprd.ko + __platform_driver_probe + # required by hid-generic.ko bus_for_each_drv hid_bus_type @@ -659,6 +722,20 @@ __hid_register_driver hid_unregister_driver +# required by i2c-sprd.ko + i2c_add_numbered_adapter + i2c_del_adapter + +# required by img_mem.ko + dma_direct_map_sg + dma_direct_sync_sg_for_cpu + dma_direct_sync_sg_for_device + dma_direct_unmap_sg + idr_get_next + sg_alloc_table + sg_free_table + vsprintf + # required by ims_bridge.ko in4_pton in6_pton @@ -684,6 +761,68 @@ strim xfrm_lookup +# required by kfifo_buf.ko + devres_add + devres_alloc_node + devres_free + devres_release + iio_buffer_init + iio_buffer_put + __kfifo_to_user + +# required by leds-sc27xx-bltc.ko + devm_led_classdev_register_ext + +# required by mali_gondul.ko + anon_inode_getfd + __bitmap_weight + clear_page + devfreq_add_device + devfreq_remove_device + devfreq_resume_device + devfreq_suspend_device + dev_pm_opp_disable + dev_pm_opp_find_freq_floor + dev_pm_opp_put_regulators + dev_pm_opp_set_regulators + dma_fence_get_status + dma_fence_remove_callback + downgrade_write + down_trylock + get_user_pages + get_user_pages_fast + get_user_pages_remote + hrtimer_active + hrtimer_forward + iomem_resource + kstrtobool_from_user + memstart_addr + __mmdrop + nonseekable_open + of_property_read_variable_u64_array + param_ops_byte + rb_erase + rb_first + rb_insert_color + rb_next + rb_prev + rb_replace_node + regulator_get_optional + __release_region + remap_vmalloc_range + __request_region + reservation_ww_class + seq_open + __seq_open_private + seq_release_private + seq_write + set_page_dirty_lock + strcspn + system_highpri_wq + vmalloc_user + ww_mutex_lock + ww_mutex_unlock + # required by microarray_fp.ko cdev_alloc @@ -730,9 +869,15 @@ pci_stop_and_remove_bus_device pci_unlock_rescan_remove +# required by phy-sprd-sharkl3.ko + usb_add_phy_dev + usb_phy_set_charger_state + usb_remove_phy + # required by pinctrl-sprd.ko devm_platform_ioremap_resource of_property_read_string_helper + pinconf_generic_parse_dt_config pinctrl_dev_get_drvdata pinctrl_register pinctrl_unregister @@ -740,6 +885,7 @@ pinctrl_utils_add_map_mux pinctrl_utils_free_map pinctrl_utils_reserve_map + pin_get_name # required by pvrsrvkm.ko autoremove_wake_function @@ -831,10 +977,31 @@ vsscanf vzalloc +# required by pwm-sprd.ko + pwmchip_add + pwmchip_remove + +# required by pwm_bl.ko + backlight_device_register + backlight_device_unregister + devm_pwm_get + gpiod_get_direction + int_pow + pwm_free + pwm_request + # required by roles.ko fwnode_connection_find_match fwnode_get_parent +# required by rtc-sc27xx.ko + devm_rtc_allocate_device + rtc_ktime_to_tm + __rtc_register_device + rtc_time64_to_tm + rtc_tm_to_time64 + rtc_update_irq + # required by sc2703-bl.ko of_pwm_get pwm_apply_state @@ -860,15 +1027,126 @@ power_supply_find_ocv2cap_table power_supply_ocv2cap_simple power_supply_put_battery_info + power_supply_temp2resist_simple # required by sc27xx_pd.ko device_get_named_child_node devm_extcon_register_notifier_all devm_regulator_get_optional +# required by sc27xx_typec.ko + devm_extcon_dev_allocate + devm_extcon_dev_register + extcon_set_state_sync + typec_register_partner + typec_register_port + typec_set_data_role + typec_set_pwr_opmode + typec_set_pwr_role + typec_set_vconn_role + typec_unregister_partner + typec_unregister_port + +# required by sc27xx-vibra.ko + input_ff_create_memless + # required by sc9863a-clk.ko device_get_match_data +# required by sdcardfs.ko + __break_lease + clear_inode + clear_nlink + configfs_register_subsystem + configfs_unregister_subsystem + config_group_init + config_group_init_type_name + config_item_init_type_name + copy_fs_struct + d_drop + dentry_open + dget_parent + d_invalidate + d_make_root + d_path + dput + d_rehash + d_set_d_op + d_splice_alias + filemap_write_and_wait + filp_close + filp_open + free_fs_struct + fscrypt_register_key_removal_notifier + fscrypt_unregister_key_removal_notifier + fs_parse + fsstack_copy_inode_size + generic_delete_inode + __generic_file_fsync + generic_permission + generic_read_dir + iget5_locked + igrab + init_special_inode + inode_init_once + inode_newsize_ok + iput + iterate_dir + kern_path + kill_anon_super + lockref_get + lock_rename + lookup_one_len_unlocked + mntget + names_cachep + notify_change2 + override_creds + path_get + path_put + prepare_creds + __put_cred + register_filesystem + revert_creds + setattr_prepare + set_fs_pwd + set_nlink + shrink_dcache_sb + strrchr + touch_atime + truncate_inode_pages + truncate_setsize + unlock_new_inode + unlock_rename + unregister_filesystem + vfs_create2 + vfs_fsync_range + vfs_get_super + vfs_mkdir2 + vfs_path_lookup + vfs_rename2 + vfs_rmdir2 + vfs_statfs + vfs_unlink2 + +# required by sdhci-sprd.ko + clk_round_rate + mmc_free_host + mmc_of_parse + mmc_regulator_set_vqmmc + mmc_remove_host + __sdhci_add_host + sdhci_cleanup_host + sdhci_enable_clk + sdhci_enable_v4_mode + sdhci_pltfm_free + sdhci_pltfm_init + sdhci_request + sdhci_reset + sdhci_runtime_resume_host + sdhci_runtime_suspend_host + sdhci_set_bus_width + sdhci_setup_host + # required by sdiohal.ko mmc_detect_change mmc_set_data_timeout @@ -926,7 +1204,6 @@ iio_device_alloc iio_device_free iio_device_unregister - kernel_write ktime_get_with_offset param_array_ops unregister_pm_notifier @@ -1014,10 +1291,31 @@ snd_soc_jack_report snd_soc_put_enum_double +# required by snd-soc-sprd-platform.ko + devm_snd_soc_register_component + dma_request_slave_channel + of_reserved_mem_device_init_by_idx + snd_dma_alloc_pages + snd_dma_free_pages + # required by snd-soc-sprd-vbc-r1p0v3.ko snd_ctl_boolean_mono_info snd_pcm_hw_constraint_list +# required by sprd-cpufreq-common.ko + dev_pm_opp_remove + +# required by sprd-cpufreqhw.ko + arch_set_freq_scale + cpufreq_generic_attr + cpufreq_generic_frequency_table_verify + cpufreq_generic_get + cpufreq_generic_suspend + cpufreq_register_driver + cpufreq_unregister_driver + dev_pm_opp_free_cpufreq_table + dev_pm_opp_init_cpufreq_table + # required by sprd-dpu.ko component_add component_bind_all @@ -1033,12 +1331,14 @@ drm_atomic_helper_async_commit drm_atomic_helper_check drm_atomic_helper_cleanup_planes + drm_atomic_helper_commit drm_atomic_helper_commit_cleanup_done drm_atomic_helper_commit_hw_done drm_atomic_helper_commit_modeset_disables drm_atomic_helper_commit_modeset_enables drm_atomic_helper_commit_planes drm_atomic_helper_commit_tail + drm_atomic_helper_commit_tail_rpm drm_atomic_helper_connector_destroy_state drm_atomic_helper_connector_duplicate_state drm_atomic_helper_connector_reset @@ -1149,6 +1449,35 @@ try_wait_for_completion vfs_write +# required by spi-sprd.ko + dma_request_chan + spi_controller_suspend + spi_finalize_current_transfer + +# required by spi-sprd-adi.ko + unregister_restart_handler + +# required by sprd-dma.ko + dma_async_device_register + dma_async_device_unregister + dma_async_tx_descriptor_init + of_dma_controller_free + of_dma_controller_register + of_dma_simple_xlate + +# required by sprd-gsp.ko + __kthread_init_worker + kthread_queue_work + kthread_worker_fn + +# required by sprd-hwdvfs-sharkl3.ko + __i2c_transfer + rt_mutex_trylock + +# required by sprd_hwspinlock.ko + hwspin_lock_register + hwspin_lock_unregister + # required by sprd-saudio.ko snd_card_free @@ -1165,6 +1494,11 @@ # required by sprd_cproc.ko of_get_parent +# required by sprd_cpu_cooling.ko + cpu_down + cpufreq_get_policy + cpu_up + # required by sprd_mcd.ko gpiod_set_value_cansleep kernel_power_off @@ -1178,6 +1512,11 @@ pci_save_state pci_set_power_state +# required by sprd_pm_domain.ko + kfree_const + kstrdup_const + of_genpd_add_subdomain + # required by sprd_powerdebug.ko cpu_pm_register_notifier pm_print_active_wakeup_sources @@ -1186,6 +1525,25 @@ # required by sprd_sdio_fm.ko vfs_llseek +# required by sprd_soc_thm.ko + thermal_zone_device_unregister + thermal_zone_device_update + thermal_zone_of_sensor_register + +# required by sprd_vdsp.ko + bsearch + devm_kstrdup + __memcpy_toio + of_match_device + of_n_addr_cells + of_n_size_cells + of_translate_address + sort + +# required by sprd_wdt.ko + devm_watchdog_register_device + watchdog_init_timeout + # required by sprdbt_sipc_tty.ko tty_schedule_flip @@ -1315,6 +1673,10 @@ usb_sg_wait usb_unlink_urb +# required by usb_f_mtp.ko + usb_os_desc_prepare_interf_dir + usb_string_id + # required by usbserial.ko device_del driver_attach @@ -1333,6 +1695,16 @@ usb_store_new_id usb_unpoison_urb +# required by vha.ko + clk_bulk_get + device_wakeup_disable + devm_iounmap + __ndelay + param_ops_long + param_ops_ulong + pm_relax + pm_stay_awake + # required by virtio_crypto.ko cpu_bit_bitmap cpus_read_lock @@ -1349,3 +1721,39 @@ scatterwalk_map_and_copy sg_init_one sg_nents_for_len + +# required by xhci-hcd.ko + dma_pool_alloc + dma_pool_create + dma_pool_destroy + dma_pool_free + __num_online_cpus + param_ops_ullong + pci_alloc_irq_vectors_affinity + pci_free_irq_vectors + pci_irq_vector + radix_tree_delete + radix_tree_insert + radix_tree_lookup + radix_tree_maybe_preload + sg_pcopy_from_buffer + sg_pcopy_to_buffer + usb_amd_dev_put + usb_amd_pt_check_port + usb_amd_quirk_pll_disable + usb_amd_quirk_pll_enable + usb_asmedia_modifyflowcontrol + usb_disable_xhci_ports + usb_hcd_end_port_resume + usb_hc_died + usb_hcd_irq + usb_hcd_start_port_resume + usb_hub_clear_tt_buffer + usb_root_hub_lost_power + usb_wakeup_notification + +# required by xhci-plat-hcd.ko + devm_clk_get_optional + of_usb_host_tpl_support + pci_bus_type + __usb_create_hcd diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h index d9ee43c6b7db..fe19f1d412e7 100644 --- a/arch/arc/include/asm/linkage.h +++ b/arch/arc/include/asm/linkage.h @@ -29,6 +29,8 @@ .endm #define ASM_NL ` /* use '`' to mark new line in macro */ +#define __ALIGN .align 4 +#define __ALIGN_STR __stringify(__ALIGN) /* annotation for data we want in DCCM - if enabled in .config */ .macro ARCFP_DATA nm diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 4d15d69ee4fa..7de15656cde8 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -309,13 +309,15 @@ endif ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) prepare: stack_protector_prepare stack_protector_prepare: prepare0 - $(eval KBUILD_CFLAGS += \ + $(eval SSP_PLUGIN_CFLAGS := \ -fplugin-arg-arm_ssp_per_task_plugin-tso=$(shell \ awk '{if ($$2 == "THREAD_SZ_ORDER") print $$3;}'\ include/generated/asm-offsets.h) \ -fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell \ awk '{if ($$2 == "TI_STACK_CANARY") print $$3;}'\ include/generated/asm-offsets.h)) + $(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS)) + $(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS)) endif all: $(notdir $(KBUILD_IMAGE)) diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 9219389bbe61..1483966dcf23 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -101,7 +101,6 @@ clean-files += piggy_data lib1funcs.S ashldi3.S bswapsdi2.S \ $(libfdt) $(libfdt_hdrs) hyp-stub.S KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING -KBUILD_CFLAGS += $(DISABLE_ARM_SSP_PER_TASK_PLUGIN) ifeq ($(CONFIG_FUNCTION_TRACER),y) ORIG_CFLAGS := $(KBUILD_CFLAGS) @@ -117,7 +116,8 @@ CFLAGS_fdt_ro.o := $(nossp_flags) CFLAGS_fdt_rw.o := $(nossp_flags) CFLAGS_fdt_wip.o := $(nossp_flags) -ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin -I$(obj) +ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin \ + -I$(obj) $(DISABLE_ARM_SSP_PER_TASK_PLUGIN) asflags-y := -DZIMAGE # Supply kernel BSS size to the decompressor via a linker symbol. diff --git a/arch/arm/boot/dts/am437x-idk-evm.dts b/arch/arm/boot/dts/am437x-idk-evm.dts index f3ced6df0c9b..9f66f96d09c9 100644 --- a/arch/arm/boot/dts/am437x-idk-evm.dts +++ b/arch/arm/boot/dts/am437x-idk-evm.dts @@ -526,11 +526,11 @@ * Supply voltage supervisor on board will not allow opp50 so * disable it and set opp100 as suspend OPP. */ - opp50@300000000 { + opp50-300000000 { status = "disabled"; }; - opp100@600000000 { + opp100-600000000 { opp-suspend; }; }; diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts index b75af21069f9..4c3f606e5b8d 100644 --- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts +++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts @@ -112,6 +112,7 @@ &sdhci { #address-cells = <1>; #size-cells = <0>; + pinctrl-names = "default"; pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>; bus-width = <4>; mmc-pwrseq = <&wifi_pwrseq>; diff --git a/arch/arm/boot/dts/dra7-l4.dtsi b/arch/arm/boot/dts/dra7-l4.dtsi index c3954e34835b..3ae4f6358da4 100644 --- a/arch/arm/boot/dts/dra7-l4.dtsi +++ b/arch/arm/boot/dts/dra7-l4.dtsi @@ -3413,6 +3413,7 @@ clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER13_CLKCTRL 24>; clock-names = "fck"; interrupts = ; + ti,timer-pwm; }; }; @@ -3441,6 +3442,7 @@ clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER14_CLKCTRL 24>; clock-names = "fck"; interrupts = ; + ti,timer-pwm; }; }; @@ -3469,6 +3471,7 @@ clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER15_CLKCTRL 24>; clock-names = "fck"; interrupts = ; + ti,timer-pwm; }; }; @@ -3497,6 +3500,7 @@ clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER16_CLKCTRL 24>; clock-names = "fck"; interrupts = ; + ti,timer-pwm; }; }; diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 953f0ffce2a9..c6be65249f42 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -148,6 +148,7 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x0 0x0 0xc0000000>; + dma-ranges = <0x80000000 0x0 0x80000000 0x80000000>; ti,hwmods = "l3_main_1", "l3_main_2"; reg = <0x0 0x44000000 0x0 0x1000000>, <0x0 0x45000000 0x0 0x1000>; @@ -184,6 +185,7 @@ device_type = "pci"; ranges = <0x81000000 0 0 0x03000 0 0x00010000 0x82000000 0 0x20013000 0x13000 0 0xffed000>; + dma-ranges = <0x02000000 0x0 0x00000000 0x00000000 0x1 0x00000000>; bus-range = <0x00 0xff>; #interrupt-cells = <1>; num-lanes = <1>; @@ -238,6 +240,7 @@ device_type = "pci"; ranges = <0x81000000 0 0 0x03000 0 0x00010000 0x82000000 0 0x30013000 0x13000 0 0xffed000>; + dma-ranges = <0x02000000 0x0 0x00000000 0x00000000 0x1 0x00000000>; bus-range = <0x00 0xff>; #interrupt-cells = <1>; num-lanes = <1>; diff --git a/arch/arm/boot/dts/dra76x.dtsi b/arch/arm/boot/dts/dra76x.dtsi index cdcba3f561c4..9f6fbe4c1fee 100644 --- a/arch/arm/boot/dts/dra76x.dtsi +++ b/arch/arm/boot/dts/dra76x.dtsi @@ -86,3 +86,8 @@ &usb4_tm { status = "disabled"; }; + +&mmc3 { + /* dra76x is not affected by i887 */ + max-frequency = <96000000>; +}; diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi index 93e1eb83bed9..d7d98d2069df 100644 --- a/arch/arm/boot/dts/dra7xx-clocks.dtsi +++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi @@ -796,16 +796,6 @@ clock-div = <1>; }; - ipu1_gfclk_mux: ipu1_gfclk_mux@520 { - #clock-cells = <0>; - compatible = "ti,mux-clock"; - clocks = <&dpll_abe_m2x2_ck>, <&dpll_core_h22x2_ck>; - ti,bit-shift = <24>; - reg = <0x0520>; - assigned-clocks = <&ipu1_gfclk_mux>; - assigned-clock-parents = <&dpll_core_h22x2_ck>; - }; - dummy_ck: dummy_ck { #clock-cells = <0>; compatible = "fixed-clock"; @@ -1564,6 +1554,8 @@ compatible = "ti,clkctrl"; reg = <0x20 0x4>; #clock-cells = <2>; + assigned-clocks = <&ipu1_clkctrl DRA7_IPU1_MMU_IPU1_CLKCTRL 24>; + assigned-clock-parents = <&dpll_core_h22x2_ck>; }; ipu_clkctrl: ipu-clkctrl@50 { diff --git a/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi index 6486df3e2942..31fa37d2fe47 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi @@ -107,14 +107,14 @@ regulators { vdd_arm: buck1 { regulator-name = "vdd_arm"; - regulator-min-microvolt = <730000>; + regulator-min-microvolt = <925000>; regulator-max-microvolt = <1380000>; regulator-always-on; }; vdd_soc: buck2 { regulator-name = "vdd_soc"; - regulator-min-microvolt = <730000>; + regulator-min-microvolt = <1150000>; regulator-max-microvolt = <1380000>; regulator-always-on; }; @@ -183,7 +183,6 @@ pinctrl-0 = <&pinctrl_usdhc4>; bus-width = <8>; non-removable; - vmmc-supply = <&vdd_emmc_1p8>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi index 917eb0b58b13..eed78f12e79e 100644 --- a/arch/arm/boot/dts/imx7-colibri.dtsi +++ b/arch/arm/boot/dts/imx7-colibri.dtsi @@ -337,7 +337,6 @@ assigned-clock-rates = <400000000>; bus-width = <8>; fsl,tuning-step = <2>; - max-frequency = <100000000>; vmmc-supply = <®_module_3v3>; vqmmc-supply = <®_DCDC3>; non-removable; diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi index 2f6977ada447..63d9f4a066e3 100644 --- a/arch/arm/boot/dts/ls1021a.dtsi +++ b/arch/arm/boot/dts/ls1021a.dtsi @@ -728,7 +728,7 @@ }; mdio0: mdio@2d24000 { - compatible = "fsl,etsec2-mdio"; + compatible = "gianfar"; device_type = "mdio"; #address-cells = <1>; #size-cells = <0>; @@ -737,7 +737,7 @@ }; mdio1: mdio@2d64000 { - compatible = "fsl,etsec2-mdio"; + compatible = "gianfar"; device_type = "mdio"; #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts index 63659880eeb3..7f2ddb78da5f 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/omap3-n900.dts @@ -849,34 +849,46 @@ compatible = "ti,omap2-onenand"; reg = <0 0 0x20000>; /* CS0, offset 0, IO size 128K */ + /* + * These timings are based on CONFIG_OMAP_GPMC_DEBUG=y reported + * bootloader set values when booted with v5.1 + * (OneNAND Manufacturer: Samsung): + * + * cs0 GPMC_CS_CONFIG1: 0xfb001202 + * cs0 GPMC_CS_CONFIG2: 0x00111100 + * cs0 GPMC_CS_CONFIG3: 0x00020200 + * cs0 GPMC_CS_CONFIG4: 0x11001102 + * cs0 GPMC_CS_CONFIG5: 0x03101616 + * cs0 GPMC_CS_CONFIG6: 0x90060000 + */ gpmc,sync-read; gpmc,sync-write; gpmc,burst-length = <16>; gpmc,burst-read; gpmc,burst-wrap; gpmc,burst-write; - gpmc,device-width = <2>; /* GPMC_DEVWIDTH_16BIT */ - gpmc,mux-add-data = <2>; /* GPMC_MUX_AD */ + gpmc,device-width = <2>; + gpmc,mux-add-data = <2>; gpmc,cs-on-ns = <0>; - gpmc,cs-rd-off-ns = <87>; - gpmc,cs-wr-off-ns = <87>; + gpmc,cs-rd-off-ns = <102>; + gpmc,cs-wr-off-ns = <102>; gpmc,adv-on-ns = <0>; - gpmc,adv-rd-off-ns = <10>; - gpmc,adv-wr-off-ns = <10>; - gpmc,oe-on-ns = <15>; - gpmc,oe-off-ns = <87>; + gpmc,adv-rd-off-ns = <12>; + gpmc,adv-wr-off-ns = <12>; + gpmc,oe-on-ns = <12>; + gpmc,oe-off-ns = <102>; gpmc,we-on-ns = <0>; - gpmc,we-off-ns = <87>; - gpmc,rd-cycle-ns = <112>; - gpmc,wr-cycle-ns = <112>; - gpmc,access-ns = <81>; - gpmc,page-burst-access-ns = <15>; + gpmc,we-off-ns = <102>; + gpmc,rd-cycle-ns = <132>; + gpmc,wr-cycle-ns = <132>; + gpmc,access-ns = <96>; + gpmc,page-burst-access-ns = <18>; gpmc,bus-turnaround-ns = <0>; gpmc,cycle2cycle-delay-ns = <0>; gpmc,wait-monitoring-ns = <0>; - gpmc,clk-activation-ns = <5>; - gpmc,wr-data-mux-bus-ns = <30>; - gpmc,wr-access-ns = <81>; + gpmc,clk-activation-ns = <6>; + gpmc,wr-data-mux-bus-ns = <36>; + gpmc,wr-access-ns = <96>; gpmc,sync-clk-ps = <15000>; /* diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 1fb7937638f0..041646fabb2d 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -143,6 +143,7 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0 0 0 0xc0000000>; + dma-ranges = <0x80000000 0x0 0x80000000 0x80000000>; ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3"; reg = <0 0x44000000 0 0x2000>, <0 0x44800000 0 0x3000>, diff --git a/arch/arm/boot/dts/ox810se.dtsi b/arch/arm/boot/dts/ox810se.dtsi index 9f6c2b660ed3..0755e5864c4a 100644 --- a/arch/arm/boot/dts/ox810se.dtsi +++ b/arch/arm/boot/dts/ox810se.dtsi @@ -323,8 +323,8 @@ interrupt-controller; reg = <0 0x200>; #interrupt-cells = <1>; - valid-mask = <0xFFFFFFFF>; - clear-mask = <0>; + valid-mask = <0xffffffff>; + clear-mask = <0xffffffff>; }; timer0: timer@200 { diff --git a/arch/arm/boot/dts/ox820.dtsi b/arch/arm/boot/dts/ox820.dtsi index c9b327732063..90846a7655b4 100644 --- a/arch/arm/boot/dts/ox820.dtsi +++ b/arch/arm/boot/dts/ox820.dtsi @@ -240,8 +240,8 @@ reg = <0 0x200>; interrupts = ; #interrupt-cells = <1>; - valid-mask = <0xFFFFFFFF>; - clear-mask = <0>; + valid-mask = <0xffffffff>; + clear-mask = <0xffffffff>; }; timer0: timer@200 { diff --git a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts index 3bec3e0a81b2..397140454132 100644 --- a/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts +++ b/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts @@ -482,7 +482,8 @@ }; &usbphy { - usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + usb0_id_det-gpios = <&pio 7 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH11 */ + usb0_vbus_power-supply = <&usb_power_supply>; usb0_vbus-supply = <®_drivevbus>; usb1_vbus-supply = <®_vmain>; usb2_vbus-supply = <®_vmain>; diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index c9c2688db66d..80f4dc34df34 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -266,6 +266,16 @@ #phy-cells = <1>; }; + ahci: sata@1c18000 { + compatible = "allwinner,sun8i-r40-ahci"; + reg = <0x01c18000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_SATA>, <&ccu CLK_SATA>; + resets = <&ccu RST_BUS_SATA>; + reset-names = "ahci"; + status = "disabled"; + }; + ehci1: usb@1c19000 { compatible = "allwinner,sun8i-r40-ehci", "generic-ehci"; reg = <0x01c19000 0x100>; @@ -557,17 +567,6 @@ #size-cells = <0>; }; - ahci: sata@1c18000 { - compatible = "allwinner,sun8i-r40-ahci"; - reg = <0x01c18000 0x1000>; - interrupts = ; - clocks = <&ccu CLK_BUS_SATA>, <&ccu CLK_SATA>; - resets = <&ccu RST_BUS_SATA>; - reset-names = "ahci"; - status = "disabled"; - - }; - gmac: ethernet@1c50000 { compatible = "allwinner,sun8i-r40-gmac"; syscon = <&ccu>; diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c index 9bf16c93ee6a..f00e45fa62c4 100644 --- a/arch/arm/kernel/vdso.c +++ b/arch/arm/kernel/vdso.c @@ -92,6 +92,8 @@ static bool __init cntvct_functional(void) * this. */ np = of_find_compatible_node(NULL, NULL, "arm,armv7-timer"); + if (!np) + np = of_find_compatible_node(NULL, NULL, "arm,armv8-timer"); if (!np) goto out_put; diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 35ff620537e6..03506ce46149 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -91,6 +91,8 @@ AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o endif +AFLAGS_resume-imx6.o :=-Wa,-march=armv7-a +obj-$(CONFIG_SOC_IMX6) += resume-imx6.o obj-$(CONFIG_SOC_IMX6) += pm-imx6.o obj-$(CONFIG_SOC_IMX1) += mach-imx1.o diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 912aeceb4ff8..5aa5796cff0e 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -109,17 +109,17 @@ void imx_cpu_die(unsigned int cpu); int imx_cpu_kill(unsigned int cpu); #ifdef CONFIG_SUSPEND -void v7_cpu_resume(void); void imx53_suspend(void __iomem *ocram_vbase); extern const u32 imx53_suspend_sz; void imx6_suspend(void __iomem *ocram_vbase); #else -static inline void v7_cpu_resume(void) {} static inline void imx53_suspend(void __iomem *ocram_vbase) {} static const u32 imx53_suspend_sz; static inline void imx6_suspend(void __iomem *ocram_vbase) {} #endif +void v7_cpu_resume(void); + void imx6_pm_ccm_init(const char *ccm_compat); void imx6q_pm_init(void); void imx6dl_pm_init(void); diff --git a/arch/arm/mach-imx/resume-imx6.S b/arch/arm/mach-imx/resume-imx6.S new file mode 100644 index 000000000000..5bd1ba7ef15b --- /dev/null +++ b/arch/arm/mach-imx/resume-imx6.S @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + */ + +#include +#include +#include +#include +#include "hardware.h" + +/* + * The following code must assume it is running from physical address + * where absolute virtual addresses to the data section have to be + * turned into relative ones. + */ + +ENTRY(v7_cpu_resume) + bl v7_invalidate_l1 +#ifdef CONFIG_CACHE_L2X0 + bl l2c310_early_resume +#endif + b cpu_resume +ENDPROC(v7_cpu_resume) diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S index 062391ff13da..1eabf2d2834b 100644 --- a/arch/arm/mach-imx/suspend-imx6.S +++ b/arch/arm/mach-imx/suspend-imx6.S @@ -327,17 +327,3 @@ resume: ret lr ENDPROC(imx6_suspend) - -/* - * The following code must assume it is running from physical address - * where absolute virtual addresses to the data section have to be - * turned into relative ones. - */ - -ENTRY(v7_cpu_resume) - bl v7_invalidate_l1 -#ifdef CONFIG_CACHE_L2X0 - bl l2c310_early_resume -#endif - b cpu_resume -ENDPROC(v7_cpu_resume) diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts index 4d67eb715b91..3f43716d5c45 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts @@ -327,7 +327,7 @@ #size-cells = <0>; bus-width = <4>; - max-frequency = <50000000>; + max-frequency = <60000000>; non-removable; disable-wp; diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts index 5d6a8dafe8dc..29ac78ddc057 100644 --- a/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts +++ b/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts @@ -363,6 +363,7 @@ compatible = "brcm,bcm43438-bt"; interrupt-parent = <&gpio_intc>; interrupts = <95 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "host-wakeup"; shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>; max-speed = <2000000>; clocks = <&wifi32k>; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi index 6082ae022136..d237162a8744 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi @@ -20,6 +20,8 @@ }; &fman0 { + fsl,erratum-a050385; + /* these aliases provide the FMan ports mapping */ enet0: ethernet@e0000 { }; diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts index 4223a2352d45..dde50c88f5e3 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts @@ -119,12 +119,12 @@ ethernet@e4000 { phy-handle = <&rgmii_phy1>; - phy-connection-type = "rgmii-txid"; + phy-connection-type = "rgmii-id"; }; ethernet@e6000 { phy-handle = <&rgmii_phy2>; - phy-connection-type = "rgmii-txid"; + phy-connection-type = "rgmii-id"; }; ethernet@e8000 { diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts index 6a6514d0e5a9..274339759114 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts @@ -127,12 +127,12 @@ &fman0 { ethernet@e4000 { phy-handle = <&rgmii_phy1>; - phy-connection-type = "rgmii"; + phy-connection-type = "rgmii-id"; }; ethernet@e6000 { phy-handle = <&rgmii_phy2>; - phy-connection-type = "rgmii"; + phy-connection-type = "rgmii-id"; }; ethernet@e8000 { diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts index 19468058e6ae..8148196902dd 100644 --- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts +++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts @@ -52,11 +52,6 @@ compatible = "ethernet-phy-ieee802.3-c22"; reg = <0>; }; - - ethphy1: ethernet-phy@1 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <1>; - }; }; }; diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi index d2cb28da3fff..d911d38877e5 100644 --- a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi +++ b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi @@ -82,7 +82,7 @@ ranges = <0 0 0 0xffffffff>; gmac0: ethernet@ff800000 { - compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac"; + compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac"; reg = <0xff800000 0x2000>; interrupts = <0 90 4>; interrupt-names = "macirq"; @@ -97,7 +97,7 @@ }; gmac1: ethernet@ff802000 { - compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac"; + compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac"; reg = <0xff802000 0x2000>; interrupts = <0 91 4>; interrupt-names = "macirq"; @@ -112,7 +112,7 @@ }; gmac2: ethernet@ff804000 { - compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac"; + compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac"; reg = <0xff804000 0x2000>; interrupts = <0 92 4>; interrupt-names = "macirq"; diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig index 1b5be47a2663..8facd9268840 100644 --- a/arch/arm64/configs/gki_defconfig +++ b/arch/arm64/configs/gki_defconfig @@ -34,11 +34,11 @@ CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y -# CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set # CONFIG_SLAB_MERGE_DEFAULT is not set CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_SLAB_FREELIST_HARDENED=y +CONFIG_SHUFFLE_PAGE_ALLOCATOR=y CONFIG_PROFILING=y CONFIG_ARCH_HISI=y CONFIG_ARCH_QCOM=y @@ -75,6 +75,7 @@ CONFIG_ARM_SCPI_PROTOCOL=y CONFIG_ARM64_CRYPTO=y CONFIG_CRYPTO_SHA2_ARM64_CE=y CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_JUMP_LABEL=y CONFIG_SHADOW_CALL_STACK=y CONFIG_LTO_CLANG=y CONFIG_CFI_CLANG=y @@ -87,6 +88,7 @@ CONFIG_GKI_HACKS_TO_FIX=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=y CONFIG_MEMORY_HOTPLUG=y +CONFIG_CLEANCACHE=y CONFIG_CMA=y CONFIG_CMA_AREAS=16 CONFIG_ZSMALLOC=y @@ -212,7 +214,6 @@ CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FW_CACHE is not set # CONFIG_ALLOW_DEV_COREDUMP is not set -CONFIG_DEBUG_DEVRES=y CONFIG_GNSS=y CONFIG_ZRAM=y CONFIG_BLK_DEV_LOOP=y @@ -307,9 +308,11 @@ CONFIG_POWER_RESET_HISI=y # CONFIG_HWMON is not set CONFIG_THERMAL=y CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y CONFIG_CPU_THERMAL=y CONFIG_DEVFREQ_THERMAL=y CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y CONFIG_MFD_ACT8945A=y CONFIG_MFD_SYSCON=y CONFIG_REGULATOR=y @@ -345,10 +348,14 @@ CONFIG_USB_OTG=y CONFIG_USB_GADGET=y CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y CONFIG_USB_CONFIGFS_F_FS=y CONFIG_USB_CONFIGFS_F_ACC=y CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_TYPEC=y CONFIG_MMC=y # CONFIG_PWRSEQ_EMMC is not set # CONFIG_PWRSEQ_SIMPLE is not set @@ -374,13 +381,14 @@ CONFIG_HWSPINLOCK=y CONFIG_MAILBOX=y CONFIG_IOMMU_LIMIT_IOVA_ALIGNMENT=y CONFIG_ARM_SMMU=y +CONFIG_REMOTEPROC=y +CONFIG_RPMSG_CHAR=y CONFIG_QCOM_COMMAND_DB=y CONFIG_QCOM_RPMH=y CONFIG_DEVFREQ_GOV_PERFORMANCE=y CONFIG_DEVFREQ_GOV_POWERSAVE=y CONFIG_DEVFREQ_GOV_USERSPACE=y CONFIG_DEVFREQ_GOV_PASSIVE=y -CONFIG_EXTCON=y CONFIG_IIO=y CONFIG_IIO_BUFFER=y CONFIG_IIO_TRIGGER=y @@ -466,8 +474,10 @@ CONFIG_NLS_MAC_TURKISH=y CONFIG_NLS_UTF8=y CONFIG_UNICODE=y CONFIG_SECURITY=y +CONFIG_SECURITYFS=y CONFIG_SECURITY_NETWORK=y CONFIG_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY_FALLBACK is not set CONFIG_FORTIFY_SOURCE=y CONFIG_SECURITY_SELINUX=y CONFIG_INIT_STACK_ALL=y @@ -491,5 +501,7 @@ CONFIG_SOFTLOCKUP_DETECTOR=y # CONFIG_DETECT_HUNG_TASK is not set CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_LIST=y CONFIG_CORESIGHT=y CONFIG_CORESIGHT_STM=y diff --git a/arch/arm64/configs/hikey960_gki.fragment b/arch/arm64/configs/hikey960_gki.fragment new file mode 100644 index 000000000000..da3526a41b3d --- /dev/null +++ b/arch/arm64/configs/hikey960_gki.fragment @@ -0,0 +1,66 @@ +CONFIG_CPUFREQ_DT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_HIDP=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_LL=y +CONFIG_RFKILL_GPIO=m +CONFIG_CONNECTOR=m +CONFIG_BLK_DEV_NVME=m +CONFIG_NVME_TARGET=m +CONFIG_HISI_HIKEY_USB=m +CONFIG_SCSI_UFS_HISI=m +CONFIG_WLAN_VENDOR_TI=y +CONFIG_WL18XX=m +CONFIG_WLCORE_SDIO=m +CONFIG_INPUT_HISI_POWERKEY=m +CONFIG_SERIO_AMBAKMI=m +CONFIG_SERIAL_8250_DW=m +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_DESIGNWARE_PLATFORM=m +CONFIG_SPI_PL022=m +CONFIG_SPI_SPIDEV=m +CONFIG_SYSCON_REBOOT_MODE=m +CONFIG_HWMON=m +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_HISI_THERMAL=m +CONFIG_MFD_HI6421_PMIC=m +CONFIG_MFD_HI655X_PMIC=m +CONFIG_REGULATOR_HI6421V530=m +CONFIG_REGULATOR_HI655X=m +CONFIG_MALI_DEVFREQ=y +CONFIG_DRM_I2C_ADV7511=m +CONFIG_DRM_I2C_ADV7511_AUDIO=y +CONFIG_DRM_HISI_KIRIN=m +CONFIG_DRM_HISI_KIRIN960=y +CONFIG_SND_I2S_HI3660_I2S=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_USB_XHCI_HCD=m +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_HCD_PLATFORM=m +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_OHCI_HCD_PLATFORM=m +CONFIG_USB_DWC3=m +CONFIG_USB_GADGETFS=m +CONFIG_TYPEC_TCPM=m +CONFIG_TYPEC_TCPCI=m +CONFIG_TYPEC_RT1711H=m +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_MINORS=64 +CONFIG_MMC_ARMMMCI=m +CONFIG_MMC_SPI=m +CONFIG_MMC_DW=m +CONFIG_MMC_DW_EXYNOS=m +CONFIG_MMC_DW_K3=m +CONFIG_RTC_DRV_EFI=m +CONFIG_K3_DMA=m +CONFIG_ION_CMA_HEAP=m +CONFIG_HI3660_MBOX=m +CONFIG_MALI_MIDGARD=m +CONFIG_MALI_PLATFORM_NAME="hisilicon" +CONFIG_MALI_EXPERT=y +CONFIG_MALI_PWRSOFT_765=y +CONFIG_PHY_HI3660_USB=m diff --git a/arch/arm64/configs/vendor/holi_GKI.config b/arch/arm64/configs/vendor/holi_GKI.config index 0466738df7c1..863b3627d038 100644 --- a/arch/arm64/configs/vendor/holi_GKI.config +++ b/arch/arm64/configs/vendor/holi_GKI.config @@ -28,7 +28,6 @@ CONFIG_USB_DWC3_MSM=m CONFIG_USB_EHSET_TEST_FIXTURE=m CONFIG_USB_LINK_LAYER_TEST=m CONFIG_USB_CONFIGFS_F_DIAG=m -CONFIG_TYPEC=m CONFIG_TYPEC_UCSI=m CONFIG_UCSI_QTI_GLINK=m CONFIG_INTERCONNECT_QCOM=m diff --git a/arch/arm64/configs/vendor/lahaina_GKI.config b/arch/arm64/configs/vendor/lahaina_GKI.config index 33d1eb03791c..8411cb925048 100644 --- a/arch/arm64/configs/vendor/lahaina_GKI.config +++ b/arch/arm64/configs/vendor/lahaina_GKI.config @@ -39,7 +39,6 @@ CONFIG_USB_CONFIGFS_F_CDEV=m CONFIG_USB_CONFIGFS_F_GSI=m CONFIG_USB_CONFIGFS_MASS_STORAGE=m CONFIG_USB_STORAGE=m -CONFIG_TYPEC=m CONFIG_SDCARD_FS=m CONFIG_TYPEC_UCSI=m CONFIG_UCSI_QTI_GLINK=m diff --git a/arch/arm64/include/asm/alternative.h b/arch/arm64/include/asm/alternative.h index 324e7d5ab37e..5e5dc05d63a0 100644 --- a/arch/arm64/include/asm/alternative.h +++ b/arch/arm64/include/asm/alternative.h @@ -221,7 +221,7 @@ alternative_endif .macro user_alt, label, oldinstr, newinstr, cond 9999: alternative_insn "\oldinstr", "\newinstr", \cond - _ASM_EXTABLE 9999b, \label + _asm_extable 9999b, \label .endm /* diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index ac1dbca3d0cd..2705ca572015 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -55,6 +55,7 @@ #define ARM64_WORKAROUND_CAVIUM_TX2_219_TVM 45 #define ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM 46 -#define ARM64_NCAPS 47 +/* kabi: reserve 48 - 62 for future cpu capabilities */ +#define ARM64_NCAPS 62 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h index d39ddb258a04..75d6cd23a679 100644 --- a/arch/arm64/include/asm/page.h +++ b/arch/arm64/include/asm/page.h @@ -21,6 +21,10 @@ extern void __cpu_copy_user_page(void *to, const void *from, extern void copy_page(void *to, const void *from); extern void clear_page(void *to); +#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \ + alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr) +#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE + #define clear_user_page(addr,vaddr,pg) __cpu_clear_user_page(addr, vaddr) #define copy_user_page(to,from,vaddr,pg) __cpu_copy_user_page(to, from, vaddr) diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 5af82587909e..8c1b73dc8f55 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -25,8 +25,8 @@ #define __NR_compat_gettimeofday 78 #define __NR_compat_sigreturn 119 #define __NR_compat_rt_sigreturn 173 -#define __NR_compat_clock_getres 247 #define __NR_compat_clock_gettime 263 +#define __NR_compat_clock_getres 264 #define __NR_compat_clock_gettime64 403 #define __NR_compat_clock_getres_time64 406 diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 436a5de71343..e87f7a0b7fc4 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -995,11 +995,22 @@ void tick_broadcast(const struct cpumask *mask) } #endif +/* + * The number of CPUs online, not counting this CPU (which may not be + * fully online and so not counted in num_online_cpus()). + */ +static inline unsigned int num_other_online_cpus(void) +{ + unsigned int this_cpu_online = cpu_online(smp_processor_id()); + + return num_online_cpus() - this_cpu_online; +} + void smp_send_stop(void) { unsigned long timeout; - if (num_online_cpus() > 1) { + if (num_other_online_cpus()) { cpumask_t mask; cpumask_copy(&mask, cpu_online_mask); @@ -1012,10 +1023,10 @@ void smp_send_stop(void) /* Wait up to one second for other CPUs to stop */ timeout = USEC_PER_SEC; - while (num_online_cpus() > 1 && timeout--) + while (num_other_online_cpus() && timeout--) udelay(1); - if (num_online_cpus() > 1) + if (num_other_online_cpus()) pr_warning("SMP: failed to stop secondary CPUs %*pbl\n", cpumask_pr_args(cpu_online_mask)); @@ -1038,7 +1049,11 @@ void crash_smp_send_stop(void) cpus_stopped = 1; - if (num_online_cpus() == 1) { + /* + * If this cpu is the only one alive at this point in time, online or + * not, there are no stop messages to be sent around, so just back out. + */ + if (num_other_online_cpus() == 0) { sdei_mask_local_cpu(); return; } @@ -1046,7 +1061,7 @@ void crash_smp_send_stop(void) cpumask_copy(&mask, cpu_online_mask); cpumask_clear_cpu(smp_processor_id(), &mask); - atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); + atomic_set(&waiting_for_crash_ipi, num_other_online_cpus()); pr_crit("SMP: stopping secondary CPUs\n"); smp_cross_call(&mask, IPI_CPU_CRASH_STOP); diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 3973847b5f42..48b2e1b59119 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -36,6 +36,7 @@ config CSKY select GX6605S_TIMER if CPU_CK610 select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_AUDITSYSCALL + select HAVE_COPY_THREAD_TLS select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER @@ -74,7 +75,7 @@ config CPU_HAS_TLBI config CPU_HAS_LDSTEX bool help - For SMP, CPU needs "ldex&stex" instrcutions to atomic operations. + For SMP, CPU needs "ldex&stex" instructions for atomic operations. config CPU_NEED_TLBSYNC bool diff --git a/arch/csky/abiv1/inc/abi/entry.h b/arch/csky/abiv1/inc/abi/entry.h index 7ab78bd0f3b1..f35a9f3315ee 100644 --- a/arch/csky/abiv1/inc/abi/entry.h +++ b/arch/csky/abiv1/inc/abi/entry.h @@ -16,14 +16,16 @@ #define LSAVE_A4 40 #define LSAVE_A5 44 +#define usp ss1 + .macro USPTOKSP - mtcr sp, ss1 + mtcr sp, usp mfcr sp, ss0 .endm .macro KSPTOUSP mtcr sp, ss0 - mfcr sp, ss1 + mfcr sp, usp .endm .macro SAVE_ALL epc_inc @@ -45,7 +47,13 @@ add lr, r13 stw lr, (sp, 8) + mov lr, sp + addi lr, 32 + addi lr, 32 + addi lr, 16 + bt 2f mfcr lr, ss1 +2: stw lr, (sp, 16) stw a0, (sp, 20) @@ -79,9 +87,10 @@ ldw a0, (sp, 12) mtcr a0, epsr btsti a0, 31 + bt 1f ldw a0, (sp, 16) mtcr a0, ss1 - +1: ldw a0, (sp, 24) ldw a1, (sp, 28) ldw a2, (sp, 32) @@ -102,9 +111,9 @@ addi sp, 32 addi sp, 8 - bt 1f + bt 2f KSPTOUSP -1: +2: rte .endm diff --git a/arch/csky/abiv2/inc/abi/entry.h b/arch/csky/abiv2/inc/abi/entry.h index 9897a16b45e5..94a7a58765df 100644 --- a/arch/csky/abiv2/inc/abi/entry.h +++ b/arch/csky/abiv2/inc/abi/entry.h @@ -31,7 +31,13 @@ mfcr lr, epsr stw lr, (sp, 12) + btsti lr, 31 + bf 1f + addi lr, sp, 152 + br 2f +1: mfcr lr, usp +2: stw lr, (sp, 16) stw a0, (sp, 20) @@ -64,8 +70,10 @@ mtcr a0, epc ldw a0, (sp, 12) mtcr a0, epsr + btsti a0, 31 ldw a0, (sp, 16) mtcr a0, usp + mtcr a0, ss0 #ifdef CONFIG_CPU_HAS_HILO ldw a0, (sp, 140) @@ -86,6 +94,9 @@ addi sp, 40 ldm r16-r30, (sp) addi sp, 72 + bf 1f + mfcr sp, ss0 +1: rte .endm diff --git a/arch/csky/include/uapi/asm/unistd.h b/arch/csky/include/uapi/asm/unistd.h index 211c983c7282..ba4018929733 100644 --- a/arch/csky/include/uapi/asm/unistd.h +++ b/arch/csky/include/uapi/asm/unistd.h @@ -1,7 +1,10 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. +#define __ARCH_WANT_STAT64 +#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_SYS_CLONE +#define __ARCH_WANT_SYS_CLONE3 #define __ARCH_WANT_SET_GET_RLIMIT #define __ARCH_WANT_TIME32_SYSCALLS #include diff --git a/arch/csky/kernel/atomic.S b/arch/csky/kernel/atomic.S index 5b84f11485ae..3821ef9b7567 100644 --- a/arch/csky/kernel/atomic.S +++ b/arch/csky/kernel/atomic.S @@ -17,10 +17,12 @@ ENTRY(csky_cmpxchg) mfcr a3, epc addi a3, TRAP0_SIZE - subi sp, 8 + subi sp, 16 stw a3, (sp, 0) mfcr a3, epsr stw a3, (sp, 4) + mfcr a3, usp + stw a3, (sp, 8) psrset ee #ifdef CONFIG_CPU_HAS_LDSTEX @@ -47,7 +49,9 @@ ENTRY(csky_cmpxchg) mtcr a3, epc ldw a3, (sp, 4) mtcr a3, epsr - addi sp, 8 + ldw a3, (sp, 8) + mtcr a3, usp + addi sp, 16 KSPTOUSP rte END(csky_cmpxchg) diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c index f320d9248a22..397962e11bd1 100644 --- a/arch/csky/kernel/process.c +++ b/arch/csky/kernel/process.c @@ -34,10 +34,11 @@ unsigned long thread_saved_pc(struct task_struct *tsk) return sw->r15; } -int copy_thread(unsigned long clone_flags, +int copy_thread_tls(unsigned long clone_flags, unsigned long usp, unsigned long kthread_arg, - struct task_struct *p) + struct task_struct *p, + unsigned long tls) { struct switch_stack *childstack; struct pt_regs *childregs = task_pt_regs(p); @@ -64,7 +65,7 @@ int copy_thread(unsigned long clone_flags, childregs->usp = usp; if (clone_flags & CLONE_SETTLS) task_thread_info(p)->tp_value = childregs->tls - = childregs->regs[0]; + = tls; childregs->a0 = 0; childstack->r15 = (unsigned long) ret_from_fork; diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c index b753d382e4ce..0bb0954d5570 100644 --- a/arch/csky/kernel/smp.c +++ b/arch/csky/kernel/smp.c @@ -120,7 +120,7 @@ void __init setup_smp_ipi(void) int rc; if (ipi_irq == 0) - panic("%s IRQ mapping failed\n", __func__); + return; rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt", &ipi_dummy_dev); diff --git a/arch/csky/mm/Makefile b/arch/csky/mm/Makefile index c94ef6481098..efb7ebab342b 100644 --- a/arch/csky/mm/Makefile +++ b/arch/csky/mm/Makefile @@ -1,8 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only ifeq ($(CONFIG_CPU_HAS_CACHEV2),y) obj-y += cachev2.o +CFLAGS_REMOVE_cachev2.o = $(CC_FLAGS_FTRACE) else obj-y += cachev1.o +CFLAGS_REMOVE_cachev1.o = $(CC_FLAGS_FTRACE) endif obj-y += dma-mapping.o diff --git a/arch/csky/mm/init.c b/arch/csky/mm/init.c index d4c2292ea46b..00e96278b377 100644 --- a/arch/csky/mm/init.c +++ b/arch/csky/mm/init.c @@ -31,6 +31,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss; pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss; +EXPORT_SYMBOL(invalid_pte_table); unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss; EXPORT_SYMBOL(empty_zero_page); diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h index 45e3137ccd71..72b81015cebe 100644 --- a/arch/powerpc/include/asm/cache.h +++ b/arch/powerpc/include/asm/cache.h @@ -55,42 +55,48 @@ struct ppc64_caches { extern struct ppc64_caches ppc64_caches; -static inline u32 l1_cache_shift(void) +static inline u32 l1_dcache_shift(void) { return ppc64_caches.l1d.log_block_size; } -static inline u32 l1_cache_bytes(void) +static inline u32 l1_dcache_bytes(void) { return ppc64_caches.l1d.block_size; } + +static inline u32 l1_icache_shift(void) +{ + return ppc64_caches.l1i.log_block_size; +} + +static inline u32 l1_icache_bytes(void) +{ + return ppc64_caches.l1i.block_size; +} #else -static inline u32 l1_cache_shift(void) +static inline u32 l1_dcache_shift(void) { return L1_CACHE_SHIFT; } -static inline u32 l1_cache_bytes(void) +static inline u32 l1_dcache_bytes(void) { return L1_CACHE_BYTES; } + +static inline u32 l1_icache_shift(void) +{ + return L1_CACHE_SHIFT; +} + +static inline u32 l1_icache_bytes(void) +{ + return L1_CACHE_BYTES; +} + #endif -#endif /* ! __ASSEMBLY__ */ -#if defined(__ASSEMBLY__) -/* - * For a snooping icache, we still need a dummy icbi to purge all the - * prefetched instructions from the ifetch buffers. We also need a sync - * before the icbi to order the the actual stores to memory that might - * have modified instructions with the icbi. - */ -#define PURGE_PREFETCHED_INS \ - sync; \ - icbi 0,r3; \ - sync; \ - isync - -#else #define __read_mostly __attribute__((__section__(".data..read_mostly"))) #ifdef CONFIG_PPC_BOOK3S_32 @@ -124,6 +130,17 @@ static inline void dcbst(void *addr) { __asm__ __volatile__ ("dcbst 0, %0" : : "r"(addr) : "memory"); } + +static inline void icbi(void *addr) +{ + asm volatile ("icbi 0, %0" : : "r"(addr) : "memory"); +} + +static inline void iccci(void *addr) +{ + asm volatile ("iccci 0, %0" : : "r"(addr) : "memory"); +} + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_CACHE_H */ diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h index eef388f2659f..4a1c9f0200e1 100644 --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h @@ -42,29 +42,25 @@ extern void flush_dcache_page(struct page *page); #define flush_dcache_mmap_lock(mapping) do { } while (0) #define flush_dcache_mmap_unlock(mapping) do { } while (0) -extern void flush_icache_range(unsigned long, unsigned long); +void flush_icache_range(unsigned long start, unsigned long stop); extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, unsigned long addr, int len); -extern void __flush_dcache_icache(void *page_va); extern void flush_dcache_icache_page(struct page *page); -#if defined(CONFIG_PPC32) && !defined(CONFIG_BOOKE) -extern void __flush_dcache_icache_phys(unsigned long physaddr); -#else -static inline void __flush_dcache_icache_phys(unsigned long physaddr) -{ - BUG(); -} -#endif +void __flush_dcache_icache(void *page); -/* - * Write any modified data cache blocks out to memory and invalidate them. - * Does not invalidate the corresponding instruction cache blocks. +/** + * flush_dcache_range(): Write any modified data cache blocks out to memory and + * invalidate them. Does not invalidate the corresponding instruction cache + * blocks. + * + * @start: the start address + * @stop: the stop address (exclusive) */ static inline void flush_dcache_range(unsigned long start, unsigned long stop) { - unsigned long shift = l1_cache_shift(); - unsigned long bytes = l1_cache_bytes(); + unsigned long shift = l1_dcache_shift(); + unsigned long bytes = l1_dcache_bytes(); void *addr = (void *)(start & ~(bytes - 1)); unsigned long size = stop - (unsigned long)addr + (bytes - 1); unsigned long i; @@ -89,8 +85,8 @@ static inline void flush_dcache_range(unsigned long start, unsigned long stop) */ static inline void clean_dcache_range(unsigned long start, unsigned long stop) { - unsigned long shift = l1_cache_shift(); - unsigned long bytes = l1_cache_bytes(); + unsigned long shift = l1_dcache_shift(); + unsigned long bytes = l1_dcache_bytes(); void *addr = (void *)(start & ~(bytes - 1)); unsigned long size = stop - (unsigned long)addr + (bytes - 1); unsigned long i; @@ -108,8 +104,8 @@ static inline void clean_dcache_range(unsigned long start, unsigned long stop) static inline void invalidate_dcache_range(unsigned long start, unsigned long stop) { - unsigned long shift = l1_cache_shift(); - unsigned long bytes = l1_cache_bytes(); + unsigned long shift = l1_dcache_shift(); + unsigned long bytes = l1_dcache_bytes(); void *addr = (void *)(start & ~(bytes - 1)); unsigned long size = stop - (unsigned long)addr + (bytes - 1); unsigned long i; diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index e745abc5457a..245be4fafe13 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -2193,11 +2193,13 @@ static struct cpu_spec * __init setup_cpu_spec(unsigned long offset, * oprofile_cpu_type already has a value, then we are * possibly overriding a real PVR with a logical one, * and, in that case, keep the current value for - * oprofile_cpu_type. + * oprofile_cpu_type. Futhermore, let's ensure that the + * fix for the PMAO bug is enabled on compatibility mode. */ if (old.oprofile_cpu_type != NULL) { t->oprofile_cpu_type = old.oprofile_cpu_type; t->oprofile_type = old.oprofile_type; + t->cpu_features |= old.cpu_features & CPU_FTR_PMAO_BUG; } } diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 82df4b09e79f..f4e4a1926a7a 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -316,126 +316,6 @@ _GLOBAL(flush_instruction_cache) EXPORT_SYMBOL(flush_instruction_cache) #endif /* CONFIG_PPC_8xx */ -/* - * Write any modified data cache blocks out to memory - * and invalidate the corresponding instruction cache blocks. - * This is a no-op on the 601. - * - * flush_icache_range(unsigned long start, unsigned long stop) - */ -_GLOBAL(flush_icache_range) -#if defined(CONFIG_PPC_BOOK3S_601) || defined(CONFIG_E200) - PURGE_PREFETCHED_INS - blr /* for 601 and e200, do nothing */ -#else - rlwinm r3,r3,0,0,31 - L1_CACHE_SHIFT - subf r4,r3,r4 - addi r4,r4,L1_CACHE_BYTES - 1 - srwi. r4,r4,L1_CACHE_SHIFT - beqlr - mtctr r4 - mr r6,r3 -1: dcbst 0,r3 - addi r3,r3,L1_CACHE_BYTES - bdnz 1b - sync /* wait for dcbst's to get to ram */ -#ifndef CONFIG_44x - mtctr r4 -2: icbi 0,r6 - addi r6,r6,L1_CACHE_BYTES - bdnz 2b -#else - /* Flash invalidate on 44x because we are passed kmapped addresses and - this doesn't work for userspace pages due to the virtually tagged - icache. Sigh. */ - iccci 0, r0 -#endif - sync /* additional sync needed on g4 */ - isync - blr -#endif -_ASM_NOKPROBE_SYMBOL(flush_icache_range) -EXPORT_SYMBOL(flush_icache_range) - -/* - * Flush a particular page from the data cache to RAM. - * Note: this is necessary because the instruction cache does *not* - * snoop from the data cache. - * This is a no-op on the 601 and e200 which have a unified cache. - * - * void __flush_dcache_icache(void *page) - */ -_GLOBAL(__flush_dcache_icache) -#if defined(CONFIG_PPC_BOOK3S_601) || defined(CONFIG_E200) - PURGE_PREFETCHED_INS - blr -#else - rlwinm r3,r3,0,0,31-PAGE_SHIFT /* Get page base address */ - li r4,PAGE_SIZE/L1_CACHE_BYTES /* Number of lines in a page */ - mtctr r4 - mr r6,r3 -0: dcbst 0,r3 /* Write line to ram */ - addi r3,r3,L1_CACHE_BYTES - bdnz 0b - sync -#ifdef CONFIG_44x - /* We don't flush the icache on 44x. Those have a virtual icache - * and we don't have access to the virtual address here (it's - * not the page vaddr but where it's mapped in user space). The - * flushing of the icache on these is handled elsewhere, when - * a change in the address space occurs, before returning to - * user space - */ -BEGIN_MMU_FTR_SECTION - blr -END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_44x) -#endif /* CONFIG_44x */ - mtctr r4 -1: icbi 0,r6 - addi r6,r6,L1_CACHE_BYTES - bdnz 1b - sync - isync - blr -#endif - -#ifndef CONFIG_BOOKE -/* - * Flush a particular page from the data cache to RAM, identified - * by its physical address. We turn off the MMU so we can just use - * the physical address (this may be a highmem page without a kernel - * mapping). - * - * void __flush_dcache_icache_phys(unsigned long physaddr) - */ -_GLOBAL(__flush_dcache_icache_phys) -#if defined(CONFIG_PPC_BOOK3S_601) || defined(CONFIG_E200) - PURGE_PREFETCHED_INS - blr /* for 601 and e200, do nothing */ -#else - mfmsr r10 - rlwinm r0,r10,0,28,26 /* clear DR */ - mtmsr r0 - isync - rlwinm r3,r3,0,0,31-PAGE_SHIFT /* Get page base address */ - li r4,PAGE_SIZE/L1_CACHE_BYTES /* Number of lines in a page */ - mtctr r4 - mr r6,r3 -0: dcbst 0,r3 /* Write line to ram */ - addi r3,r3,L1_CACHE_BYTES - bdnz 0b - sync - mtctr r4 -1: icbi 0,r6 - addi r6,r6,L1_CACHE_BYTES - bdnz 1b - sync - mtmsr r10 /* restore DR */ - isync - blr -#endif -#endif /* CONFIG_BOOKE */ - /* * Copy a whole page. We use the dcbz instruction on the destination * to reduce memory traffic (it eliminates the unnecessary reads of diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 9bc0aa9aeb65..ff20c253f273 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -49,108 +49,6 @@ _GLOBAL(call_do_irq) mtlr r0 blr - .section ".toc","aw" -PPC64_CACHES: - .tc ppc64_caches[TC],ppc64_caches - .section ".text" - -/* - * Write any modified data cache blocks out to memory - * and invalidate the corresponding instruction cache blocks. - * - * flush_icache_range(unsigned long start, unsigned long stop) - * - * flush all bytes from start through stop-1 inclusive - */ - -_GLOBAL_TOC(flush_icache_range) -BEGIN_FTR_SECTION - PURGE_PREFETCHED_INS - blr -END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) -/* - * Flush the data cache to memory - * - * Different systems have different cache line sizes - * and in some cases i-cache and d-cache line sizes differ from - * each other. - */ - ld r10,PPC64_CACHES@toc(r2) - lwz r7,DCACHEL1BLOCKSIZE(r10)/* Get cache block size */ - addi r5,r7,-1 - andc r6,r3,r5 /* round low to line bdy */ - subf r8,r6,r4 /* compute length */ - add r8,r8,r5 /* ensure we get enough */ - lwz r9,DCACHEL1LOGBLOCKSIZE(r10) /* Get log-2 of cache block size */ - srd. r8,r8,r9 /* compute line count */ - beqlr /* nothing to do? */ - mtctr r8 -1: dcbst 0,r6 - add r6,r6,r7 - bdnz 1b - sync - -/* Now invalidate the instruction cache */ - - lwz r7,ICACHEL1BLOCKSIZE(r10) /* Get Icache block size */ - addi r5,r7,-1 - andc r6,r3,r5 /* round low to line bdy */ - subf r8,r6,r4 /* compute length */ - add r8,r8,r5 - lwz r9,ICACHEL1LOGBLOCKSIZE(r10) /* Get log-2 of Icache block size */ - srd. r8,r8,r9 /* compute line count */ - beqlr /* nothing to do? */ - mtctr r8 -2: icbi 0,r6 - add r6,r6,r7 - bdnz 2b - isync - blr -_ASM_NOKPROBE_SYMBOL(flush_icache_range) -EXPORT_SYMBOL(flush_icache_range) - -/* - * Flush a particular page from the data cache to RAM. - * Note: this is necessary because the instruction cache does *not* - * snoop from the data cache. - * - * void __flush_dcache_icache(void *page) - */ -_GLOBAL(__flush_dcache_icache) -/* - * Flush the data cache to memory - * - * Different systems have different cache line sizes - */ - -BEGIN_FTR_SECTION - PURGE_PREFETCHED_INS - blr -END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) - -/* Flush the dcache */ - ld r7,PPC64_CACHES@toc(r2) - clrrdi r3,r3,PAGE_SHIFT /* Page align */ - lwz r4,DCACHEL1BLOCKSPERPAGE(r7) /* Get # dcache blocks per page */ - lwz r5,DCACHEL1BLOCKSIZE(r7) /* Get dcache block size */ - mr r6,r3 - mtctr r4 -0: dcbst 0,r6 - add r6,r6,r5 - bdnz 0b - sync - -/* Now invalidate the icache */ - - lwz r4,ICACHEL1BLOCKSPERPAGE(r7) /* Get # icache blocks per page */ - lwz r5,ICACHEL1BLOCKSIZE(r7) /* Get icache block size */ - mtctr r4 -1: icbi 0,r3 - add r3,r3,r5 - bdnz 1b - isync - blr - _GLOBAL(__bswapdi2) EXPORT_SYMBOL(__bswapdi2) srdi r8,r3,32 diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 060a1acd7c6d..4638d2863388 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -326,6 +326,12 @@ SECTIONS *(.branch_lt) } +#ifdef CONFIG_DEBUG_INFO_BTF + .BTF : AT(ADDR(.BTF) - LOAD_OFFSET) { + *(.BTF) + } +#endif + .opd : AT(ADDR(.opd) - LOAD_OFFSET) { __start_opd = .; KEEP(*(.opd)) diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 9f5b32163bda..96ca90ce0264 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -348,6 +348,122 @@ void free_initmem(void) free_initmem_default(POISON_FREE_INITMEM); } +/** + * flush_coherent_icache() - if a CPU has a coherent icache, flush it + * @addr: The base address to use (can be any valid address, the whole cache will be flushed) + * Return true if the cache was flushed, false otherwise + */ +static inline bool flush_coherent_icache(unsigned long addr) +{ + /* + * For a snooping icache, we still need a dummy icbi to purge all the + * prefetched instructions from the ifetch buffers. We also need a sync + * before the icbi to order the the actual stores to memory that might + * have modified instructions with the icbi. + */ + if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) { + mb(); /* sync */ + allow_read_from_user((const void __user *)addr, L1_CACHE_BYTES); + icbi((void *)addr); + prevent_read_from_user((const void __user *)addr, L1_CACHE_BYTES); + mb(); /* sync */ + isync(); + return true; + } + + return false; +} + +/** + * invalidate_icache_range() - Flush the icache by issuing icbi across an address range + * @start: the start address + * @stop: the stop address (exclusive) + */ +static void invalidate_icache_range(unsigned long start, unsigned long stop) +{ + unsigned long shift = l1_icache_shift(); + unsigned long bytes = l1_icache_bytes(); + char *addr = (char *)(start & ~(bytes - 1)); + unsigned long size = stop - (unsigned long)addr + (bytes - 1); + unsigned long i; + + for (i = 0; i < size >> shift; i++, addr += bytes) + icbi(addr); + + mb(); /* sync */ + isync(); +} + +/** + * flush_icache_range: Write any modified data cache blocks out to memory + * and invalidate the corresponding blocks in the instruction cache + * + * Generic code will call this after writing memory, before executing from it. + * + * @start: the start address + * @stop: the stop address (exclusive) + */ +void flush_icache_range(unsigned long start, unsigned long stop) +{ + if (flush_coherent_icache(start)) + return; + + clean_dcache_range(start, stop); + + if (IS_ENABLED(CONFIG_44x)) { + /* + * Flash invalidate on 44x because we are passed kmapped + * addresses and this doesn't work for userspace pages due to + * the virtually tagged icache. + */ + iccci((void *)start); + mb(); /* sync */ + isync(); + } else + invalidate_icache_range(start, stop); +} +EXPORT_SYMBOL(flush_icache_range); + +#if !defined(CONFIG_PPC_8xx) && !defined(CONFIG_PPC64) +/** + * flush_dcache_icache_phys() - Flush a page by it's physical address + * @physaddr: the physical address of the page + */ +static void flush_dcache_icache_phys(unsigned long physaddr) +{ + unsigned long bytes = l1_dcache_bytes(); + unsigned long nb = PAGE_SIZE / bytes; + unsigned long addr = physaddr & PAGE_MASK; + unsigned long msr, msr0; + unsigned long loop1 = addr, loop2 = addr; + + msr0 = mfmsr(); + msr = msr0 & ~MSR_DR; + /* + * This must remain as ASM to prevent potential memory accesses + * while the data MMU is disabled + */ + asm volatile( + " mtctr %2;\n" + " mtmsr %3;\n" + " isync;\n" + "0: dcbst 0, %0;\n" + " addi %0, %0, %4;\n" + " bdnz 0b;\n" + " sync;\n" + " mtctr %2;\n" + "1: icbi 0, %1;\n" + " addi %1, %1, %4;\n" + " bdnz 1b;\n" + " sync;\n" + " mtmsr %5;\n" + " isync;\n" + : "+&r" (loop1), "+&r" (loop2) + : "r" (nb), "r" (msr), "i" (bytes), "r" (msr0) + : "ctr", "memory"); +} +#endif // !defined(CONFIG_PPC_8xx) && !defined(CONFIG_PPC64) + /* * This is called when a page has been modified by the kernel. * It just marks the page as not i-cache clean. We do the i-cache @@ -380,12 +496,46 @@ void flush_dcache_icache_page(struct page *page) __flush_dcache_icache(start); kunmap_atomic(start); } else { - __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT); + unsigned long addr = page_to_pfn(page) << PAGE_SHIFT; + + if (flush_coherent_icache(addr)) + return; + flush_dcache_icache_phys(addr); } #endif } EXPORT_SYMBOL(flush_dcache_icache_page); +/** + * __flush_dcache_icache(): Flush a particular page from the data cache to RAM. + * Note: this is necessary because the instruction cache does *not* + * snoop from the data cache. + * + * @page: the address of the page to flush + */ +void __flush_dcache_icache(void *p) +{ + unsigned long addr = (unsigned long)p; + + if (flush_coherent_icache(addr)) + return; + + clean_dcache_range(addr, addr + PAGE_SIZE); + + /* + * We don't flush the icache on 44x. Those have a virtual icache and we + * don't have access to the virtual address here (it's not the page + * vaddr but where it's mapped in user space). The flushing of the + * icache on these is handled elsewhere, when a change in the address + * space occurs, before returning to user space. + */ + + if (cpu_has_feature(MMU_FTR_TYPE_44x)) + return; + + invalidate_icache_range(addr, addr + PAGE_SIZE); +} + void clear_user_page(void *page, unsigned long vaddr, struct page *pg) { clear_page(page); diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index ade9699aa0dd..a0fa4be94a68 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -101,6 +101,7 @@ config ARCH_FLATMEM_ENABLE config ARCH_SPARSEMEM_ENABLE def_bool y + depends on MMU select SPARSEMEM_VMEMMAP_ENABLE config ARCH_SELECT_MEMORY_MODEL diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c index 70bb94ae61c5..6bf5b1674384 100644 --- a/arch/riscv/kernel/module.c +++ b/arch/riscv/kernel/module.c @@ -8,6 +8,10 @@ #include #include #include +#include +#include +#include +#include static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v) { @@ -386,3 +390,15 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, return 0; } + +#if defined(CONFIG_MMU) && defined(CONFIG_64BIT) +#define VMALLOC_MODULE_START \ + max(PFN_ALIGN((unsigned long)&_end - SZ_2G), VMALLOC_START) +void *module_alloc(unsigned long size) +{ + return __vmalloc_node_range(size, 1, VMALLOC_MODULE_START, + VMALLOC_END, GFP_KERNEL, + PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, + __builtin_return_address(0)); +} +#endif diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 573463d1c799..f5d813c1304d 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -98,7 +98,7 @@ void __init setup_bootmem(void) for_each_memblock(memory, reg) { phys_addr_t end = reg->base + reg->size; - if (reg->base <= vmlinux_end && vmlinux_end <= end) { + if (reg->base <= vmlinux_start && vmlinux_end <= end) { mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET); /* diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 9ce1baeac2b2..2faaf456956a 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -146,7 +146,7 @@ all: bzImage #KBUILD_IMAGE is necessary for packaging targets like rpm-pkg, deb-pkg... KBUILD_IMAGE := $(boot)/bzImage -install: vmlinux +install: $(Q)$(MAKE) $(build)=$(boot) $@ bzImage: vmlinux diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index e2c47d3a1c89..0ff9261c915e 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile @@ -70,7 +70,7 @@ $(obj)/compressed/vmlinux: $(obj)/startup.a FORCE $(obj)/startup.a: $(OBJECTS) FORCE $(call if_changed,ar) -install: $(CONFIGURE) $(obj)/bzImage +install: sh -x $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/bzImage \ System.map "$(INSTALL_PATH)" diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index a9e46b83c536..34a655ad7123 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -756,6 +756,12 @@ static inline int pmd_write(pmd_t pmd) return (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) != 0; } +#define pud_write pud_write +static inline int pud_write(pud_t pud) +{ + return (pud_val(pud) & _REGION3_ENTRY_WRITE) != 0; +} + static inline int pmd_dirty(pmd_t pmd) { int dirty = 1; diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index e3f238e8c611..4f35b1055f30 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -227,7 +227,7 @@ struct qdio_buffer { * @sbal: absolute SBAL address */ struct sl_element { - unsigned long sbal; + u64 sbal; } __attribute__ ((packed)); /** diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 5b24fcc9c361..6105b1b6e49b 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -423,7 +423,7 @@ static void zpci_map_resources(struct pci_dev *pdev) if (zpci_use_mio(zdev)) pdev->resource[i].start = - (resource_size_t __force) zdev->bars[i].mio_wb; + (resource_size_t __force) zdev->bars[i].mio_wt; else pdev->resource[i].start = (resource_size_t __force) pci_iomap_range_fh(pdev, i, 0, 0); @@ -530,7 +530,7 @@ static int zpci_setup_bus_resources(struct zpci_dev *zdev, flags |= IORESOURCE_MEM_64; if (zpci_use_mio(zdev)) - addr = (unsigned long) zdev->bars[i].mio_wb; + addr = (unsigned long) zdev->bars[i].mio_wt; else addr = ZPCI_ADDR(entry); size = 1UL << zdev->bars[i].size; diff --git a/arch/x86/boot/compressed/kaslr_64.c b/arch/x86/boot/compressed/kaslr_64.c index 748456c365f4..9557c5a15b91 100644 --- a/arch/x86/boot/compressed/kaslr_64.c +++ b/arch/x86/boot/compressed/kaslr_64.c @@ -29,9 +29,6 @@ #define __PAGE_OFFSET __PAGE_OFFSET_BASE #include "../../mm/ident_map.c" -/* Used by pgtable.h asm code to force instruction serialization. */ -unsigned long __force_order; - /* Used to track our page table allocation area. */ struct alloc_pgt_data { unsigned char *pgt_buf; diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig index b0236103daf8..b2c6135b76a3 100644 --- a/arch/x86/configs/gki_defconfig +++ b/arch/x86/configs/gki_defconfig @@ -34,11 +34,11 @@ CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y # CONFIG_RSEQ is not set CONFIG_EMBEDDED=y -# CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set # CONFIG_SLAB_MERGE_DEFAULT is not set CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_SLAB_FREELIST_HARDENED=y +CONFIG_SHUFFLE_PAGE_ALLOCATOR=y CONFIG_PROFILING=y CONFIG_SMP=y CONFIG_HYPERVISOR_GUEST=y @@ -53,6 +53,7 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_IA32_EMULATION=y +CONFIG_JUMP_LABEL=y CONFIG_LTO_CLANG=y CONFIG_CFI_CLANG=y CONFIG_MODULES=y @@ -63,6 +64,7 @@ CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y CONFIG_GKI_HACKS_TO_FIX=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_BINFMT_MISC=y +CONFIG_CLEANCACHE=y CONFIG_CMA=y CONFIG_CMA_AREAS=16 CONFIG_ZSMALLOC=y @@ -185,7 +187,6 @@ CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FW_CACHE is not set # CONFIG_ALLOW_DEV_COREDUMP is not set -CONFIG_DEBUG_DEVRES=y CONFIG_GNSS=y CONFIG_OF=y CONFIG_ZRAM=y @@ -264,9 +265,11 @@ CONFIG_HPET=y CONFIG_SPI=y CONFIG_GPIOLIB=y # CONFIG_HWMON is not set +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y CONFIG_DEVFREQ_THERMAL=y # CONFIG_X86_PKG_TEMP_THERMAL is not set CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_CORE=y CONFIG_MFD_SYSCON=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y @@ -298,6 +301,9 @@ CONFIG_USB_HIDDEV=y CONFIG_USB_GADGET=y CONFIG_USB_CONFIGFS=y CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y CONFIG_USB_CONFIGFS_F_FS=y CONFIG_USB_CONFIGFS_F_ACC=y CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y @@ -317,6 +323,8 @@ CONFIG_STAGING=y CONFIG_ASHMEM=y CONFIG_ION=y CONFIG_ION_SYSTEM_HEAP=y +CONFIG_REMOTEPROC=y +CONFIG_RPMSG_CHAR=y CONFIG_PM_DEVFREQ=y CONFIG_IIO=y CONFIG_IIO_BUFFER=y @@ -401,8 +409,10 @@ CONFIG_NLS_MAC_TURKISH=y CONFIG_NLS_UTF8=y CONFIG_UNICODE=y CONFIG_SECURITY=y +CONFIG_SECURITYFS=y CONFIG_SECURITY_NETWORK=y CONFIG_HARDENED_USERCOPY=y +# CONFIG_HARDENED_USERCOPY_FALLBACK is not set CONFIG_FORTIFY_SOURCE=y CONFIG_SECURITY_SELINUX=y CONFIG_INIT_STACK_ALL=y @@ -427,3 +437,4 @@ CONFIG_SOFTLOCKUP_DETECTOR=y # CONFIG_DETECT_HUNG_TASK is not set CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y +CONFIG_DEBUG_LIST=y diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c index a6ea07f2aa84..4d867a752f0e 100644 --- a/arch/x86/events/amd/uncore.c +++ b/arch/x86/events/amd/uncore.c @@ -190,15 +190,12 @@ static int amd_uncore_event_init(struct perf_event *event) /* * NB and Last level cache counters (MSRs) are shared across all cores - * that share the same NB / Last level cache. Interrupts can be directed - * to a single target core, however, event counts generated by processes - * running on other cores cannot be masked out. So we do not support - * sampling and per-thread events. + * that share the same NB / Last level cache. On family 16h and below, + * Interrupts can be directed to a single target core, however, event + * counts generated by processes running on other cores cannot be masked + * out. So we do not support sampling and per-thread events via + * CAP_NO_INTERRUPT, and we do not enable counter overflow interrupts: */ - if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) - return -EINVAL; - - /* and we do not enable counter overflow interrupts */ hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB; hwc->idx = -1; @@ -306,7 +303,7 @@ static struct pmu amd_nb_pmu = { .start = amd_uncore_start, .stop = amd_uncore_stop, .read = amd_uncore_read, - .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT, }; static struct pmu amd_llc_pmu = { @@ -317,7 +314,7 @@ static struct pmu amd_llc_pmu = { .start = amd_uncore_start, .stop = amd_uncore_stop, .read = amd_uncore_read, - .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT, }; static struct amd_uncore *amd_uncore_alloc(unsigned int cpu) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index fffe21945374..704caec136cf 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -464,7 +464,7 @@ static __always_inline void setup_pku(struct cpuinfo_x86 *c) * cpuid bit to be set. We need to ensure that we * update that bit in this CPU's "cpu_info". */ - get_cpu_cap(c); + set_cpu_cap(c, X86_FEATURE_OSPKE); } #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS diff --git a/arch/x86/kernel/cpu/mce/intel.c b/arch/x86/kernel/cpu/mce/intel.c index 88cd9598fa57..f2350967a898 100644 --- a/arch/x86/kernel/cpu/mce/intel.c +++ b/arch/x86/kernel/cpu/mce/intel.c @@ -489,17 +489,18 @@ static void intel_ppin_init(struct cpuinfo_x86 *c) return; if ((val & 3UL) == 1UL) { - /* PPIN available but disabled: */ + /* PPIN locked in disabled mode */ return; } - /* If PPIN is disabled, but not locked, try to enable: */ - if (!(val & 3UL)) { + /* If PPIN is disabled, try to enable */ + if (!(val & 2UL)) { wrmsrl_safe(MSR_PPIN_CTL, val | 2UL); rdmsrl_safe(MSR_PPIN_CTL, &val); } - if ((val & 3UL) == 2UL) + /* Is the enable bit set? */ + if (val & 2UL) set_cpu_cap(c, X86_FEATURE_INTEL_PPIN); } } diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 37aa9ce29b33..128d3ad46e96 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -5197,6 +5197,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ctxt->fetch.ptr = ctxt->fetch.data; ctxt->fetch.end = ctxt->fetch.data + insn_len; ctxt->opcode_len = 1; + ctxt->intercept = x86_intercept_none; if (insn_len > 0) memcpy(ctxt->fetch.data, insn, insn_len); else { diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index e1d8062ef12e..2b44554baf28 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -223,7 +223,7 @@ static inline void nested_release_evmcs(struct kvm_vcpu *vcpu) return; kvm_vcpu_unmap(vcpu, &vmx->nested.hv_evmcs_map, true); - vmx->nested.hv_evmcs_vmptr = -1ull; + vmx->nested.hv_evmcs_vmptr = 0; vmx->nested.hv_evmcs = NULL; } @@ -1828,7 +1828,8 @@ static int nested_vmx_handle_enlightened_vmptrld(struct kvm_vcpu *vcpu, if (!nested_enlightened_vmentry(vcpu, &evmcs_gpa)) return 1; - if (unlikely(evmcs_gpa != vmx->nested.hv_evmcs_vmptr)) { + if (unlikely(!vmx->nested.hv_evmcs || + evmcs_gpa != vmx->nested.hv_evmcs_vmptr)) { if (!vmx->nested.hv_evmcs) vmx->nested.current_vmptr = -1ull; diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 304d31d8cbbc..c494c8c05824 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -189,7 +189,7 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) return pmd_k; } -void vmalloc_sync_all(void) +static void vmalloc_sync(void) { unsigned long address; @@ -216,6 +216,16 @@ void vmalloc_sync_all(void) } } +void vmalloc_sync_mappings(void) +{ + vmalloc_sync(); +} + +void vmalloc_sync_unmappings(void) +{ + vmalloc_sync(); +} + /* * 32-bit: * @@ -318,11 +328,23 @@ out: #else /* CONFIG_X86_64: */ -void vmalloc_sync_all(void) +void vmalloc_sync_mappings(void) { + /* + * 64-bit mappings might allocate new p4d/pud pages + * that need to be propagated to all tasks' PGDs. + */ sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END); } +void vmalloc_sync_unmappings(void) +{ + /* + * Unmappings never allocate or free p4d/pud pages. + * No work is required here. + */ +} + /* * 64-bit: * diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index a39dcdb5ae34..a353f88d299d 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -106,6 +106,22 @@ static unsigned int __ioremap_check_encrypted(struct resource *res) return 0; } +/* + * The EFI runtime services data area is not covered by walk_mem_res(), but must + * be mapped encrypted when SEV is active. + */ +static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *desc) +{ + if (!sev_active()) + return; + + if (!IS_ENABLED(CONFIG_EFI)) + return; + + if (efi_mem_type(addr) == EFI_RUNTIME_SERVICES_DATA) + desc->flags |= IORES_MAP_ENCRYPTED; +} + static int __ioremap_collect_map_flags(struct resource *res, void *arg) { struct ioremap_desc *desc = arg; @@ -124,6 +140,9 @@ static int __ioremap_collect_map_flags(struct resource *res, void *arg) * To avoid multiple resource walks, this function walks resources marked as * IORESOURCE_MEM and IORESOURCE_BUSY and looking for system RAM and/or a * resource described not as IORES_DESC_NONE (e.g. IORES_DESC_ACPI_TABLES). + * + * After that, deal with misc other ranges in __ioremap_check_other() which do + * not fall into the above category. */ static void __ioremap_check_mem(resource_size_t addr, unsigned long size, struct ioremap_desc *desc) @@ -135,6 +154,8 @@ static void __ioremap_check_mem(resource_size_t addr, unsigned long size, memset(desc, 0, sizeof(struct ioremap_desc)); walk_mem_res(start, end, desc, __ioremap_collect_map_flags); + + __ioremap_check_other(addr, desc); } /* diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c index 393d251798c0..4d2a7a764602 100644 --- a/arch/x86/net/bpf_jit_comp32.c +++ b/arch/x86/net/bpf_jit_comp32.c @@ -2039,10 +2039,12 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, } /* and dreg_lo,sreg_lo */ EMIT2(0x23, add_2reg(0xC0, sreg_lo, dreg_lo)); - /* and dreg_hi,sreg_hi */ - EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi)); - /* or dreg_lo,dreg_hi */ - EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi)); + if (is_jmp64) { + /* and dreg_hi,sreg_hi */ + EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi)); + /* or dreg_lo,dreg_hi */ + EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi)); + } goto emit_cond_jmp; } case BPF_JMP | BPF_JSET | BPF_K: diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 52a1e5192fa8..fe0e647411da 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -316,7 +316,7 @@ void efi_sync_low_kernel_mappings(void) static inline phys_addr_t virt_to_phys_or_null_size(void *va, unsigned long size) { - bool bad_size; + phys_addr_t pa; if (!va) return 0; @@ -324,16 +324,13 @@ virt_to_phys_or_null_size(void *va, unsigned long size) if (virt_addr_valid(va)) return virt_to_phys(va); - /* - * A fully aligned variable on the stack is guaranteed not to - * cross a page bounary. Try to catch strings on the stack by - * checking that 'size' is a power of two. - */ - bad_size = size > PAGE_SIZE || !is_power_of_2(size); + pa = slow_virt_to_phys(va); - WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size); + /* check if the object crosses a page boundary */ + if (WARN_ON((pa ^ (pa + size - 1)) & PAGE_MASK)) + return 0; - return slow_virt_to_phys(va); + return pa; } #define virt_to_phys_or_null(addr) \ @@ -791,6 +788,8 @@ static efi_status_t efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor, u32 *attr, unsigned long *data_size, void *data) { + u8 buf[24] __aligned(8); + efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd)); efi_status_t status; u32 phys_name, phys_vendor, phys_attr; u32 phys_data_size, phys_data; @@ -798,14 +797,19 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor, spin_lock_irqsave(&efi_runtime_lock, flags); + *vnd = *vendor; + phys_data_size = virt_to_phys_or_null(data_size); - phys_vendor = virt_to_phys_or_null(vendor); + phys_vendor = virt_to_phys_or_null(vnd); phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); phys_attr = virt_to_phys_or_null(attr); phys_data = virt_to_phys_or_null_size(data, *data_size); - status = efi_thunk(get_variable, phys_name, phys_vendor, - phys_attr, phys_data_size, phys_data); + if (!phys_name || (data && !phys_data)) + status = EFI_INVALID_PARAMETER; + else + status = efi_thunk(get_variable, phys_name, phys_vendor, + phys_attr, phys_data_size, phys_data); spin_unlock_irqrestore(&efi_runtime_lock, flags); @@ -816,19 +820,25 @@ static efi_status_t efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor, u32 attr, unsigned long data_size, void *data) { + u8 buf[24] __aligned(8); + efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd)); u32 phys_name, phys_vendor, phys_data; efi_status_t status; unsigned long flags; spin_lock_irqsave(&efi_runtime_lock, flags); + *vnd = *vendor; + phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); - phys_vendor = virt_to_phys_or_null(vendor); + phys_vendor = virt_to_phys_or_null(vnd); phys_data = virt_to_phys_or_null_size(data, data_size); - /* If data_size is > sizeof(u32) we've got problems */ - status = efi_thunk(set_variable, phys_name, phys_vendor, - attr, data_size, phys_data); + if (!phys_name || !phys_data) + status = EFI_INVALID_PARAMETER; + else + status = efi_thunk(set_variable, phys_name, phys_vendor, + attr, data_size, phys_data); spin_unlock_irqrestore(&efi_runtime_lock, flags); @@ -840,6 +850,8 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor, u32 attr, unsigned long data_size, void *data) { + u8 buf[24] __aligned(8); + efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd)); u32 phys_name, phys_vendor, phys_data; efi_status_t status; unsigned long flags; @@ -847,13 +859,17 @@ efi_thunk_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor, if (!spin_trylock_irqsave(&efi_runtime_lock, flags)) return EFI_NOT_READY; + *vnd = *vendor; + phys_name = virt_to_phys_or_null_size(name, efi_name_size(name)); - phys_vendor = virt_to_phys_or_null(vendor); + phys_vendor = virt_to_phys_or_null(vnd); phys_data = virt_to_phys_or_null_size(data, data_size); - /* If data_size is > sizeof(u32) we've got problems */ - status = efi_thunk(set_variable, phys_name, phys_vendor, - attr, data_size, phys_data); + if (!phys_name || !phys_data) + status = EFI_INVALID_PARAMETER; + else + status = efi_thunk(set_variable, phys_name, phys_vendor, + attr, data_size, phys_data); spin_unlock_irqrestore(&efi_runtime_lock, flags); @@ -865,21 +881,29 @@ efi_thunk_get_next_variable(unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) { + u8 buf[24] __aligned(8); + efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd)); efi_status_t status; u32 phys_name_size, phys_name, phys_vendor; unsigned long flags; spin_lock_irqsave(&efi_runtime_lock, flags); + *vnd = *vendor; + phys_name_size = virt_to_phys_or_null(name_size); - phys_vendor = virt_to_phys_or_null(vendor); + phys_vendor = virt_to_phys_or_null(vnd); phys_name = virt_to_phys_or_null_size(name, *name_size); - status = efi_thunk(get_next_variable, phys_name_size, - phys_name, phys_vendor); + if (!phys_name) + status = EFI_INVALID_PARAMETER; + else + status = efi_thunk(get_next_variable, phys_name_size, + phys_name, phys_vendor); spin_unlock_irqrestore(&efi_runtime_lock, flags); + *vendor = *vnd; return status; } diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 6ea215cdeada..6d4d8a5700b7 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -905,14 +905,15 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err) static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) { int ret; +#ifdef CONFIG_X86_64 + unsigned int which; + u64 base; +#endif ret = 0; switch (msr) { #ifdef CONFIG_X86_64 - unsigned which; - u64 base; - case MSR_FS_BASE: which = SEGBASE_FS; goto set; case MSR_KERNEL_GS_BASE: which = SEGBASE_GS_USER; goto set; case MSR_GS_BASE: which = SEGBASE_GS_KERNEL; goto set; diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c index 86a607cf19a1..86cd718e0380 100644 --- a/block/bfq-cgroup.c +++ b/block/bfq-cgroup.c @@ -332,7 +332,7 @@ static void bfqg_put(struct bfq_group *bfqg) kfree(bfqg); } -static void bfqg_and_blkg_get(struct bfq_group *bfqg) +void bfqg_and_blkg_get(struct bfq_group *bfqg) { /* see comments in bfq_bic_update_cgroup for why refcounting bfqg */ bfqg_get(bfqg); @@ -593,12 +593,13 @@ struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, */ entity = &bfqg->entity; for_each_entity(entity) { - bfqg = container_of(entity, struct bfq_group, entity); - if (bfqg != bfqd->root_group) { - parent = bfqg_parent(bfqg); + struct bfq_group *curr_bfqg = container_of(entity, + struct bfq_group, entity); + if (curr_bfqg != bfqd->root_group) { + parent = bfqg_parent(curr_bfqg); if (!parent) parent = bfqd->root_group; - bfq_group_set_parent(bfqg, parent); + bfq_group_set_parent(curr_bfqg, parent); } } @@ -634,6 +635,12 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, bfq_bfqq_expire(bfqd, bfqd->in_service_queue, false, BFQQE_PREEMPTED); + /* + * get extra reference to prevent bfqq from being freed in + * next possible deactivate + */ + bfqq->ref++; + if (bfq_bfqq_busy(bfqq)) bfq_deactivate_bfqq(bfqd, bfqq, false, false); else if (entity->on_st) @@ -653,6 +660,8 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, if (!bfqd->in_service_queue && !bfqd->rq_in_driver) bfq_schedule_dispatch(bfqd); + /* release extra ref taken above */ + bfq_put_queue(bfqq); } /** @@ -1380,6 +1389,10 @@ struct bfq_group *bfqq_group(struct bfq_queue *bfqq) return bfqq->bfqd->root_group; } +void bfqg_and_blkg_get(struct bfq_group *bfqg) {} + +void bfqg_and_blkg_put(struct bfq_group *bfqg) {} + struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node) { struct bfq_group *bfqg; diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 5498d05b873d..48189ff88916 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -614,6 +614,10 @@ bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq) bfqq->pos_root = NULL; } + /* oom_bfqq does not participate in queue merging */ + if (bfqq == &bfqd->oom_bfqq) + return; + /* * bfqq cannot be merged any longer (see comments in * bfq_setup_cooperator): no point in adding bfqq into the @@ -4822,9 +4826,7 @@ void bfq_put_queue(struct bfq_queue *bfqq) { struct bfq_queue *item; struct hlist_node *n; -#ifdef CONFIG_BFQ_GROUP_IOSCHED struct bfq_group *bfqg = bfqq_group(bfqq); -#endif if (bfqq->bfqd) bfq_log_bfqq(bfqq->bfqd, bfqq, "put_queue: %p %d", @@ -4897,9 +4899,7 @@ void bfq_put_queue(struct bfq_queue *bfqq) bfqq->bfqd->last_completed_rq_bfqq = NULL; kmem_cache_free(bfq_pool, bfqq); -#ifdef CONFIG_BFQ_GROUP_IOSCHED bfqg_and_blkg_put(bfqg); -#endif } static void bfq_put_cooperator(struct bfq_queue *bfqq) @@ -6383,10 +6383,10 @@ static void bfq_exit_queue(struct elevator_queue *e) hrtimer_cancel(&bfqd->idle_slice_timer); -#ifdef CONFIG_BFQ_GROUP_IOSCHED /* release oom-queue reference to root group */ bfqg_and_blkg_put(bfqd->root_group); +#ifdef CONFIG_BFQ_GROUP_IOSCHED blkcg_deactivate_policy(bfqd->queue, &blkcg_policy_bfq); #else spin_lock_irq(&bfqd->lock); diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h index 5d1a519640f6..1553a4e8f7ad 100644 --- a/block/bfq-iosched.h +++ b/block/bfq-iosched.h @@ -916,6 +916,7 @@ struct bfq_group { #else struct bfq_group { + struct bfq_entity entity; struct bfq_sched_data sched_data; struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; @@ -978,6 +979,7 @@ struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg); struct bfq_group *bfqq_group(struct bfq_queue *bfqq); struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node); +void bfqg_and_blkg_get(struct bfq_group *bfqg); void bfqg_and_blkg_put(struct bfq_group *bfqg); #ifdef CONFIG_BFQ_GROUP_IOSCHED diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c index 05f0bf4a1144..44079147e396 100644 --- a/block/bfq-wf2q.c +++ b/block/bfq-wf2q.c @@ -536,7 +536,9 @@ static void bfq_get_entity(struct bfq_entity *entity) bfqq->ref++; bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", bfqq, bfqq->ref); - } + } else + bfqg_and_blkg_get(container_of(entity, struct bfq_group, + entity)); } /** @@ -650,8 +652,14 @@ static void bfq_forget_entity(struct bfq_service_tree *st, entity->on_st = false; st->wsum -= entity->weight; - if (bfqq && !is_in_service) + if (is_in_service) + return; + + if (bfqq) bfq_put_queue(bfqq); + else + bfqg_and_blkg_put(container_of(entity, struct bfq_group, + entity)); } /** diff --git a/block/blk-flush.c b/block/blk-flush.c index b1f0a1ac505c..5aa6fada2259 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -399,7 +399,7 @@ void blk_insert_flush(struct request *rq) */ if ((policy & REQ_FSEQ_DATA) && !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) { - blk_mq_request_bypass_insert(rq, false); + blk_mq_request_bypass_insert(rq, false, false); return; } diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 27ca68621137..9a599cc28c29 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -1318,7 +1318,7 @@ static bool iocg_is_idle(struct ioc_gq *iocg) return false; /* is something in flight? */ - if (atomic64_read(&iocg->done_vtime) < atomic64_read(&iocg->vtime)) + if (atomic64_read(&iocg->done_vtime) != atomic64_read(&iocg->vtime)) return false; return true; diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index ca22afd47b3d..74cedea56034 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -361,13 +361,19 @@ static bool blk_mq_sched_bypass_insert(struct blk_mq_hw_ctx *hctx, bool has_sched, struct request *rq) { - /* dispatch flush rq directly */ - if (rq->rq_flags & RQF_FLUSH_SEQ) { - spin_lock(&hctx->lock); - list_add(&rq->queuelist, &hctx->dispatch); - spin_unlock(&hctx->lock); + /* + * dispatch flush and passthrough rq directly + * + * passthrough request has to be added to hctx->dispatch directly. + * For some reason, device may be in one situation which can't + * handle FS request, so STS_RESOURCE is always returned and the + * FS request will be added to hctx->dispatch. However passthrough + * request may be required at that time for fixing the problem. If + * passthrough request is added to scheduler queue, there isn't any + * chance to dispatch it given we prioritize requests in hctx->dispatch. + */ + if ((rq->rq_flags & RQF_FLUSH_SEQ) || blk_rq_is_passthrough(rq)) return true; - } if (has_sched) rq->rq_flags |= RQF_SORTED; @@ -391,8 +397,32 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head, WARN_ON(e && (rq->tag != -1)); - if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) + if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) { + /* + * Firstly normal IO request is inserted to scheduler queue or + * sw queue, meantime we add flush request to dispatch queue( + * hctx->dispatch) directly and there is at most one in-flight + * flush request for each hw queue, so it doesn't matter to add + * flush request to tail or front of the dispatch queue. + * + * Secondly in case of NCQ, flush request belongs to non-NCQ + * command, and queueing it will fail when there is any + * in-flight normal IO request(NCQ command). When adding flush + * rq to the front of hctx->dispatch, it is easier to introduce + * extra time to flush rq's latency because of S_SCHED_RESTART + * compared with adding to the tail of dispatch queue, then + * chance of flush merge is increased, and less flush requests + * will be issued to controller. It is observed that ~10% time + * is saved in blktests block/004 on disk attached to AHCI/NCQ + * drive when adding flush rq to the front of hctx->dispatch. + * + * Simply queue flush rq to the front of hctx->dispatch so that + * intensive flush workloads can benefit in case of NCQ HW. + */ + at_head = (rq->rq_flags & RQF_FLUSH_SEQ) ? true : at_head; + blk_mq_request_bypass_insert(rq, at_head, false); goto run; + } if (e && e->type->ops.insert_requests) { LIST_HEAD(list); diff --git a/block/blk-mq.c b/block/blk-mq.c index ec791156e9cc..3c1abab1fdf5 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -761,7 +761,7 @@ static void blk_mq_requeue_work(struct work_struct *work) * merge. */ if (rq->rq_flags & RQF_DONTPREP) - blk_mq_request_bypass_insert(rq, false); + blk_mq_request_bypass_insert(rq, false, false); else blk_mq_sched_insert_request(rq, true, false, false); } @@ -1313,7 +1313,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list, q->mq_ops->commit_rqs(hctx); spin_lock(&hctx->lock); - list_splice_init(list, &hctx->dispatch); + list_splice_tail_init(list, &hctx->dispatch); spin_unlock(&hctx->lock); /* @@ -1668,12 +1668,16 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, * Should only be used carefully, when the caller knows we want to * bypass a potential IO scheduler on the target device. */ -void blk_mq_request_bypass_insert(struct request *rq, bool run_queue) +void blk_mq_request_bypass_insert(struct request *rq, bool at_head, + bool run_queue) { struct blk_mq_hw_ctx *hctx = rq->mq_hctx; spin_lock(&hctx->lock); - list_add_tail(&rq->queuelist, &hctx->dispatch); + if (at_head) + list_add(&rq->queuelist, &hctx->dispatch); + else + list_add_tail(&rq->queuelist, &hctx->dispatch); spin_unlock(&hctx->lock); if (run_queue) @@ -1863,7 +1867,7 @@ insert: if (bypass_insert) return BLK_STS_RESOURCE; - blk_mq_request_bypass_insert(rq, run_queue); + blk_mq_request_bypass_insert(rq, false, run_queue); return BLK_STS_OK; } @@ -1879,7 +1883,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx, ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false, true); if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) - blk_mq_request_bypass_insert(rq, true); + blk_mq_request_bypass_insert(rq, false, true); else if (ret != BLK_STS_OK) blk_mq_end_request(rq, ret); @@ -1913,7 +1917,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx, if (ret != BLK_STS_OK) { if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) { - blk_mq_request_bypass_insert(rq, + blk_mq_request_bypass_insert(rq, false, list_empty(list)); break; } diff --git a/block/blk-mq.h b/block/blk-mq.h index 32c62c64e6c2..f2075978db50 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -66,7 +66,8 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, */ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, bool at_head); -void blk_mq_request_bypass_insert(struct request *rq, bool run_queue); +void blk_mq_request_bypass_insert(struct request *rq, bool at_head, + bool run_queue); void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx, struct list_head *list); diff --git a/build.config.allmodconfig.arm b/build.config.allmodconfig.arm new file mode 100644 index 000000000000..5dd94819c871 --- /dev/null +++ b/build.config.allmodconfig.arm @@ -0,0 +1,4 @@ +. ${ROOT_DIR}/common/build.config.common +. ${ROOT_DIR}/common/build.config.arm +. ${ROOT_DIR}/common/build.config.allmodconfig + diff --git a/build.config.arm b/build.config.arm new file mode 100644 index 000000000000..8eb547e21593 --- /dev/null +++ b/build.config.arm @@ -0,0 +1,12 @@ +ARCH=arm + +CLANG_TRIPLE=arm-linux-gnueabi- +CROSS_COMPILE=arm-linux-androidkernel- +LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin + +FILES=" +arch/arm/boot/Image.gz +arch/arm/boot/Image +vmlinux +System.map +" diff --git a/build.config.common b/build.config.common index a5451866ed10..d13238a363c6 100644 --- a/build.config.common +++ b/build.config.common @@ -5,7 +5,7 @@ CC=clang LD=ld.lld NM=llvm-nm OBJCOPY=llvm-objcopy -CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r377782b/bin +CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r377782c/bin BUILDTOOLS_PREBUILT_BIN=build/build-tools/path/linux-x86 EXTRA_CMDS='' diff --git a/build.config.cuttlefish.aarch64 b/build.config.cuttlefish.aarch64 deleted file mode 100644 index 9a685095e934..000000000000 --- a/build.config.cuttlefish.aarch64 +++ /dev/null @@ -1,11 +0,0 @@ -. ${ROOT_DIR}/common/build.config.common -. ${ROOT_DIR}/common/build.config.aarch64 -. ${ROOT_DIR}/common/build.config.gki - -BUILD_INITRAMFS=1 -DEFCONFIG=cf_aarch_64_gki_defconfig -PRE_DEFCONFIG_CMDS="KCONFIG_CONFIG=${ROOT_DIR}/common/arch/arm64/configs/${DEFCONFIG} ${ROOT_DIR}/common/scripts/kconfig/merge_config.sh -m -r ${ROOT_DIR}/common/arch/arm64/configs/gki_defconfig ${ROOT_DIR}/common/cuttlefish.fragment" -POST_DEFCONFIG_CMDS="rm ${ROOT_DIR}/common/arch/arm64/configs/${DEFCONFIG}" - -# Not saving any kernel images. This build step is meant purely to generate the .kos. -FILES="" diff --git a/build.config.cuttlefish.x86_64 b/build.config.cuttlefish.x86_64 deleted file mode 100644 index d6ce5c3a7306..000000000000 --- a/build.config.cuttlefish.x86_64 +++ /dev/null @@ -1,11 +0,0 @@ -. ${ROOT_DIR}/common/build.config.common -. ${ROOT_DIR}/common/build.config.x86_64 -. ${ROOT_DIR}/common/build.config.gki - -BUILD_INITRAMFS=1 -DEFCONFIG=cf_x86_64_gki_defconfig -PRE_DEFCONFIG_CMDS="KCONFIG_CONFIG=${ROOT_DIR}/common/arch/x86/configs/${DEFCONFIG} ${ROOT_DIR}/common/scripts/kconfig/merge_config.sh -m -r ${ROOT_DIR}/common/arch/x86/configs/gki_defconfig ${ROOT_DIR}/common/cuttlefish.fragment" -POST_DEFCONFIG_CMDS="rm ${ROOT_DIR}/common/arch/x86/configs/${DEFCONFIG}" - -# Not saving any kernel images. This build step is meant purely to generate the .kos. -FILES="" diff --git a/build.config.db845c b/build.config.db845c index 65b768fb1fb3..c6be07d937ed 100644 --- a/build.config.db845c +++ b/build.config.db845c @@ -2,8 +2,8 @@ . ${ROOT_DIR}/common/build.config.aarch64 DEFCONFIG=db845c_gki_defconfig -PRE_DEFCONFIG_CMDS="cat ./common/arch/arm64/configs/gki_defconfig ./common/arch/arm64/configs/db845c_gki.fragment > ./common/arch/arm64/configs/${DEFCONFIG};" -POST_DEFCONFIG_CMDS="rm ./common/arch/arm64/configs/${DEFCONFIG}" +PRE_DEFCONFIG_CMDS="KCONFIG_CONFIG=${ROOT_DIR}/common/arch/arm64/configs/${DEFCONFIG} ${ROOT_DIR}/common/scripts/kconfig/merge_config.sh -m -r ${ROOT_DIR}/common/arch/arm64/configs/gki_defconfig ${ROOT_DIR}/common/arch/arm64/configs/db845c_gki.fragment" +POST_DEFCONFIG_CMDS="rm ${ROOT_DIR}/common/arch/arm64/configs/${DEFCONFIG}" FILES=" arch/arm64/boot/Image.gz diff --git a/build.config.gki-debug.aarch64 b/build.config.gki-debug.aarch64 new file mode 100644 index 000000000000..54c8e15b1e27 --- /dev/null +++ b/build.config.gki-debug.aarch64 @@ -0,0 +1,2 @@ +. ${ROOT_DIR}/common/build.config.gki.aarch64 +TRIM_NONLISTED_KMI="" diff --git a/build.config.gki-debug.x86_64 b/build.config.gki-debug.x86_64 new file mode 100644 index 000000000000..136620fd536f --- /dev/null +++ b/build.config.gki-debug.x86_64 @@ -0,0 +1,2 @@ +. ${ROOT_DIR}/common/build.config.gki.x86_64 +TRIM_NONLISTED_KMI="" diff --git a/build.config.gki.aarch64 b/build.config.gki.aarch64 index cbe513cf5d8e..8b681cdb3746 100644 --- a/build.config.gki.aarch64 +++ b/build.config.gki.aarch64 @@ -7,6 +7,9 @@ KMI_WHITELIST=abi_gki_aarch64_whitelist ADDITIONAL_KMI_WHITELISTS=" abi_gki_aarch64_cuttlefish_whitelist abi_gki_aarch64_db845c_whitelist +abi_gki_aarch64_goldfish_whitelist +abi_gki_aarch64_hikey960_whitelist +abi_gki_aarch64_qcom_whitelist abi_gki_aarch64_unisoc_whitelist " TRIM_NONLISTED_KMI=1 diff --git a/build.config.hikey960 b/build.config.hikey960 new file mode 100644 index 000000000000..11d3e26435f0 --- /dev/null +++ b/build.config.hikey960 @@ -0,0 +1,17 @@ +. ${ROOT_DIR}/common/build.config.common +. ${ROOT_DIR}/common/build.config.aarch64 + +DEFCONFIG=hikey960_gki_defconfig +PRE_DEFCONFIG_CMDS="cat ./common/arch/arm64/configs/gki_defconfig ./common/arch/arm64/configs/hikey960_gki.fragment > ./common/arch/arm64/configs/${DEFCONFIG};" +POST_DEFCONFIG_CMDS="rm ./common/arch/arm64/configs/${DEFCONFIG}" + +EXT_MODULES=" +hikey-modules/midgard +" + +FILES=" +arch/arm64/boot/Image.gz +arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dtb +vmlinux +System.map +" diff --git a/cuttlefish.fragment b/cuttlefish.fragment deleted file mode 100644 index cdc0831d4e51..000000000000 --- a/cuttlefish.fragment +++ /dev/null @@ -1,20 +0,0 @@ -CONFIG_CPUFREQ_DUMMY=m -CONFIG_VSOCKETS=m -CONFIG_VIRTIO_VSOCKETS=m -CONFIG_GNSS_CMDLINE_SERIAL=m -CONFIG_VIRTIO_BLK=m -CONFIG_VIRTIO_NET=m -CONFIG_VIRT_WIFI=m -CONFIG_HW_RANDOM_VIRTIO=m -CONFIG_DRM_VIRTIO_GPU=m -CONFIG_SND_INTEL8X0=m -CONFIG_USB_DUMMY_HCD=m -CONFIG_RTC_DRV_TEST=m -CONFIG_VIRTIO_PCI=m -CONFIG_VIRTIO_PMEM=m -CONFIG_VIRTIO_INPUT=m -CONFIG_VIRTIO_MMIO=m -CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y -CONFIG_TEST_STACKINIT=m -CONFIG_TEST_MEMINIT=m -CONFIG_SDCARD_FS=m diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c index d827a4a3e946..6e9ec6e3fe47 100644 --- a/drivers/acpi/acpi_watchdog.c +++ b/drivers/acpi/acpi_watchdog.c @@ -55,12 +55,14 @@ static bool acpi_watchdog_uses_rtc(const struct acpi_table_wdat *wdat) } #endif +static bool acpi_no_watchdog; + static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void) { const struct acpi_table_wdat *wdat = NULL; acpi_status status; - if (acpi_disabled) + if (acpi_disabled || acpi_no_watchdog) return NULL; status = acpi_get_table(ACPI_SIG_WDAT, 0, @@ -88,6 +90,14 @@ bool acpi_has_watchdog(void) } EXPORT_SYMBOL_GPL(acpi_has_watchdog); +/* ACPI watchdog can be disabled on boot command line */ +static int __init disable_acpi_watchdog(char *str) +{ + acpi_no_watchdog = true; + return 1; +} +__setup("acpi_no_watchdog", disable_acpi_watchdog); + void __init acpi_watchdog_init(void) { const struct acpi_wdat_entry *entries; diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 777f6f7122b4..e0d82fab1f44 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -171,7 +171,7 @@ int ghes_estatus_pool_init(int num_ghes) * New allocation must be visible in all pgd before it can be found by * an NMI allocating from the pool. */ - vmalloc_sync_all(); + vmalloc_sync_mappings(); rc = gen_pool_add(ghes_estatus_pool, addr, PAGE_ALIGN(len), -1); if (rc) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 827530dae682..ce59a3f32eac 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -977,6 +977,16 @@ static int acpi_s2idle_prepare_late(void) return 0; } +static void acpi_s2idle_sync(void) +{ + /* + * The EC driver uses the system workqueue and an additional special + * one, so those need to be flushed too. + */ + acpi_ec_flush_work(); + acpi_os_wait_events_complete(); /* synchronize Notify handling */ +} + static bool acpi_s2idle_wake(void) { if (!acpi_sci_irq_valid()) @@ -1021,13 +1031,8 @@ static bool acpi_s2idle_wake(void) * should be missed by canceling the wakeup here. */ pm_system_cancel_wakeup(); - /* - * The EC driver uses the system workqueue and an additional - * special one, so those need to be flushed too. - */ - acpi_os_wait_events_complete(); /* synchronize EC GPE processing */ - acpi_ec_flush_work(); - acpi_os_wait_events_complete(); /* synchronize Notify handling */ + + acpi_s2idle_sync(); /* * The SCI is in the "suspended" state now and it cannot produce @@ -1055,6 +1060,13 @@ static void acpi_s2idle_restore_early(void) static void acpi_s2idle_restore(void) { + /* + * Drain pending events before restoring the working-state configuration + * of GPEs. + */ + acpi_os_wait_events_complete(); /* synchronize GPE processing */ + acpi_s2idle_sync(); + s2idle_wakeup = false; acpi_enable_all_runtime_gpes(); diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 9b56a5a231ef..9c0e74b96e4d 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2911,50 +2911,19 @@ static bool binder_proc_transaction(struct binder_transaction *t, struct binder_priority node_prio; bool oneway = !!(t->flags & TF_ONE_WAY); bool pending_async = false; - bool retry = false; BUG_ON(!node); - -set_thread_prio: + binder_node_lock(node); node_prio.prio = node->min_priority; node_prio.sched_policy = node->sched_policy; - if (thread) { - /* - * Priority must be set outside of lock, but must be - * done before enqueuing the transaction. - */ - binder_transaction_priority(thread->task, t, node_prio, - node->inherit_rt); - } - -retry_after_prio_restore: - binder_node_lock(node); if (oneway) { - BUG_ON(!retry && thread); + BUG_ON(thread); if (node->has_async_transaction) { pending_async = true; } else { node->has_async_transaction = true; } - if (thread && pending_async) { - /* - * The node state has changed since we selected - * the thread. Return the thread to the - * waiting_threads list. We have to drop - * the node lock to restore priority so we - * have to re-check the node state. - */ - binder_node_unlock(node); - binder_restore_priority(thread->task, - proc->default_priority); - binder_inner_proc_lock(proc); - list_add(&thread->waiting_thread_node, - &proc->waiting_threads); - binder_inner_proc_unlock(proc); - thread = NULL; - goto retry_after_prio_restore; - } } binder_inner_proc_lock(proc); @@ -2965,24 +2934,18 @@ retry_after_prio_restore: return false; } - if (!thread && !pending_async) { + if (!thread && !pending_async) thread = binder_select_thread_ilocked(proc); - if (thread) { - if (oneway) - node->has_async_transaction = false; - binder_inner_proc_unlock(proc); - binder_node_unlock(node); - retry = true; - goto set_thread_prio; - } - } - if (thread) + if (thread) { + binder_transaction_priority(thread->task, t, node_prio, + node->inherit_rt); binder_enqueue_thread_work_ilocked(thread, &t->work); - else if (!pending_async) + } else if (!pending_async) { binder_enqueue_work_ilocked(&t->work, &proc->todo); - else + } else { binder_enqueue_work_ilocked(&t->work, &node->async_todo); + } if (!pending_async) binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); @@ -5444,6 +5407,7 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_dev = container_of(filp->private_data, struct binder_device, miscdev); } + refcount_inc(&binder_dev->ref); proc->context = &binder_dev->context; binder_alloc_init(&proc->alloc); @@ -5621,6 +5585,7 @@ static int binder_node_release(struct binder_node *node, int refs) static void binder_deferred_release(struct binder_proc *proc) { struct binder_context *context = proc->context; + struct binder_device *device; struct rb_node *n; int threads, nodes, incoming_refs, outgoing_refs, active_transactions; @@ -5637,6 +5602,12 @@ static void binder_deferred_release(struct binder_proc *proc) context->binder_context_mgr_node = NULL; } mutex_unlock(&context->context_mgr_node_lock); + device = container_of(proc->context, struct binder_device, context); + if (refcount_dec_and_test(&device->ref)) { + kfree(context->name); + kfree(device); + } + proc->context = NULL; binder_inner_proc_lock(proc); /* * Make sure proc stays alive after we @@ -6295,6 +6266,7 @@ static int __init init_binder_device(const char *name) binder_device->miscdev.minor = MISC_DYNAMIC_MINOR; binder_device->miscdev.name = name; + refcount_set(&binder_device->ref, 1); binder_device->context.binder_context_mgr_uid = INVALID_UID; binder_device->context.name = name; mutex_init(&binder_device->context.context_mgr_node_lock); diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h index ae991097d14d..283d3cb9c16e 100644 --- a/drivers/android/binder_internal.h +++ b/drivers/android/binder_internal.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ struct binder_device { struct miscdevice miscdev; struct binder_context context; struct inode *binderfs_inode; + refcount_t ref; }; /** diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index 94bb668599a3..305c935e4b85 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c @@ -154,6 +154,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode, if (!name) goto err; + refcount_set(&device->ref, 1); device->binderfs_inode = inode; device->context.binder_context_mgr_uid = INVALID_UID; device->context.name = name; @@ -257,8 +258,10 @@ static void binderfs_evict_inode(struct inode *inode) ida_free(&binderfs_minors, device->miscdev.minor); mutex_unlock(&binderfs_minors_mutex); - kfree(device->context.name); - kfree(device); + if (refcount_dec_and_test(&device->ref)) { + kfree(device->context.name); + kfree(device); + } } /** @@ -445,6 +448,7 @@ static int binderfs_binder_ctl_create(struct super_block *sb) inode->i_uid = info->root_uid; inode->i_gid = info->root_gid; + refcount_set(&device->ref, 1); device->binderfs_inode = inode; device->miscdev.minor = minor; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 1787e3ad9c44..d33528033042 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -393,6 +393,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/ { PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */ + { PCI_VDEVICE(INTEL, 0x06d7), board_ahci }, /* Comet Lake-H RAID */ { PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */ { PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */ { PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */ diff --git a/drivers/base/core.c b/drivers/base/core.c index a341427a31cf..376c60eb5908 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -523,9 +523,13 @@ static void device_link_add_missing_supplier_links(void) mutex_lock(&wfs_lock); list_for_each_entry_safe(dev, tmp, &wait_for_suppliers, - links.needs_suppliers) - if (!fwnode_call_int_op(dev->fwnode, add_links, dev)) + links.needs_suppliers) { + int ret = fwnode_call_int_op(dev->fwnode, add_links, dev); + if (!ret) list_del_init(&dev->links.needs_suppliers); + else if (ret != -ENODEV) + dev->links.need_for_probe = false; + } mutex_unlock(&wfs_lock); } @@ -718,6 +722,8 @@ static void __device_links_queue_sync_state(struct device *dev, { struct device_link *link; + if (!dev_has_sync_state(dev)) + return; if (dev->state_synced) return; @@ -819,7 +825,7 @@ late_initcall(sync_state_resume_initcall); static void __device_links_supplier_defer_sync(struct device *sup) { - if (list_empty(&sup->links.defer_sync)) + if (list_empty(&sup->links.defer_sync) && dev_has_sync_state(sup)) list_add_tail(&sup->links.defer_sync, &deferred_sync); } diff --git a/drivers/base/memory.c b/drivers/base/memory.c index a0d5491afdb9..91c67bb85ec5 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -114,30 +114,13 @@ static ssize_t phys_index_show(struct device *dev, } /* - * Show whether the memory block is likely to be offlineable (or is already - * offline). Once offline, the memory block could be removed. The return - * value does, however, not indicate that there is a way to remove the - * memory block. + * Legacy interface that we cannot remove. Always indicate "removable" + * with CONFIG_MEMORY_HOTREMOVE - bad heuristic. */ static ssize_t removable_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct memory_block *mem = to_memory_block(dev); - unsigned long pfn; - int ret = 1, i; - - if (mem->state != MEM_ONLINE) - goto out; - - for (i = 0; i < sections_per_block; i++) { - if (!present_section_nr(mem->start_section_nr + i)) - continue; - pfn = section_nr_to_pfn(mem->start_section_nr + i); - ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION); - } - -out: - return sprintf(buf, "%d\n", ret); + return sprintf(buf, "%d\n", (int)IS_ENABLED(CONFIG_MEMORY_HOTREMOVE)); } /* diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 60386a32208f..604a461848c9 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -335,10 +335,10 @@ static void setup_pdev_dma_masks(struct platform_device *pdev) { if (!pdev->dev.coherent_dma_mask) pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - if (!pdev->dma_mask) - pdev->dma_mask = DMA_BIT_MASK(32); - if (!pdev->dev.dma_mask) - pdev->dev.dma_mask = &pdev->dma_mask; + if (!pdev->dev.dma_mask) { + pdev->platform_dma_mask = DMA_BIT_MASK(32); + pdev->dev.dma_mask = &pdev->platform_dma_mask; + } }; /** @@ -634,20 +634,8 @@ struct platform_device *platform_device_register_full( pdev->dev.of_node_reused = pdevinfo->of_node_reused; if (pdevinfo->dma_mask) { - /* - * This memory isn't freed when the device is put, - * I don't have a nice idea for that though. Conceptually - * dma_mask in struct device should not be a pointer. - * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 - */ - pdev->dev.dma_mask = - kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); - if (!pdev->dev.dma_mask) - goto err; - - kmemleak_ignore(pdev->dev.dma_mask); - - *pdev->dev.dma_mask = pdevinfo->dma_mask; + pdev->platform_dma_mask = pdevinfo->dma_mask; + pdev->dev.dma_mask = &pdev->platform_dma_mask; pdev->dev.coherent_dma_mask = pdevinfo->dma_mask; } @@ -672,7 +660,6 @@ struct platform_device *platform_device_register_full( if (ret) { err: ACPI_COMPANION_SET(&pdev->dev, NULL); - kfree(pdev->dev.dma_mask); platform_device_put(pdev); return ERR_PTR(ret); } diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index f817bc651ed3..9378a4907f86 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -341,10 +341,12 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx, err = virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num); if (err) { virtqueue_kick(vblk->vqs[qid].vq); - blk_mq_stop_hw_queue(hctx); + /* Don't stop the queue if -ENOMEM: we may have failed to + * bounce the buffer due to global resource outage. + */ + if (err == -ENOSPC) + blk_mq_stop_hw_queue(hctx); spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); - /* Out of mem doesn't actually happen, since we fall back - * to direct descriptors */ if (err == -ENOMEM || err == -ENOSPC) return BLK_STS_DEV_RESOURCE; return BLK_STS_IOERR; diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 8cc21ad7cf29..ec69e5dd7bd3 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -14,19 +14,33 @@ #define VERSION "0.1" -int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) +int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version, + enum qca_btsoc_type soc_type) { struct sk_buff *skb; struct edl_event_hdr *edl; - struct rome_version *ver; + struct qca_btsoc_version *ver; char cmd; int err = 0; + u8 event_type = HCI_EV_VENDOR; + u8 rlen = sizeof(*edl) + sizeof(*ver); + u8 rtype = EDL_APP_VER_RES_EVT; bt_dev_dbg(hdev, "QCA Version Request"); + /* Unlike other SoC's sending version command response as payload to + * VSE event. WCN3991 sends version command response as a payload to + * command complete event. + */ + if (soc_type == QCA_WCN3991) { + event_type = 0; + rlen += 1; + rtype = EDL_PATCH_VER_REQ_CMD; + } + cmd = EDL_PATCH_VER_REQ_CMD; skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN, - &cmd, HCI_EV_VENDOR, HCI_INIT_TIMEOUT); + &cmd, event_type, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { err = PTR_ERR(skb); bt_dev_err(hdev, "Reading QCA version information failed (%d)", @@ -34,7 +48,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) return err; } - if (skb->len != sizeof(*edl) + sizeof(*ver)) { + if (skb->len != rlen) { bt_dev_err(hdev, "QCA Version size mismatch len %d", skb->len); err = -EILSEQ; goto out; @@ -48,18 +62,21 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) } if (edl->cresp != EDL_CMD_REQ_RES_EVT || - edl->rtype != EDL_APP_VER_RES_EVT) { + edl->rtype != rtype) { bt_dev_err(hdev, "QCA Wrong packet received %d %d", edl->cresp, edl->rtype); err = -EIO; goto out; } - ver = (struct rome_version *)(edl->data); + if (soc_type == QCA_WCN3991) + memmove(&edl->data, &edl->data[1], sizeof(*ver)); + + ver = (struct qca_btsoc_version *)(edl->data); BT_DBG("%s: Product:0x%08x", hdev->name, le32_to_cpu(ver->product_id)); BT_DBG("%s: Patch :0x%08x", hdev->name, le16_to_cpu(ver->patch_ver)); - BT_DBG("%s: ROM :0x%08x", hdev->name, le16_to_cpu(ver->rome_ver)); + BT_DBG("%s: ROM :0x%08x", hdev->name, le16_to_cpu(ver->rom_ver)); BT_DBG("%s: SOC :0x%08x", hdev->name, le32_to_cpu(ver->soc_id)); /* QCA chipset version can be decided by patch and SoC @@ -67,7 +84,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) * and lower 2 bytes from patch will be used. */ *soc_version = (le32_to_cpu(ver->soc_id) << 16) | - (le16_to_cpu(ver->rome_ver) & 0x0000ffff); + (le16_to_cpu(ver->rom_ver) & 0x0000ffff); if (*soc_version == 0) err = -EILSEQ; @@ -121,7 +138,7 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) } EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd); -static void qca_tlv_check_data(struct rome_config *config, +static void qca_tlv_check_data(struct qca_fw_config *config, const struct firmware *fw) { const u8 *data; @@ -140,8 +157,8 @@ static void qca_tlv_check_data(struct rome_config *config, BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff); BT_DBG("Length\t\t : %d bytes", length); - config->dnld_mode = ROME_SKIP_EVT_NONE; - config->dnld_type = ROME_SKIP_EVT_NONE; + config->dnld_mode = QCA_SKIP_EVT_NONE; + config->dnld_type = QCA_SKIP_EVT_NONE; switch (config->type) { case TLV_TYPE_PATCH: @@ -223,31 +240,45 @@ static void qca_tlv_check_data(struct rome_config *config, } static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, - const u8 *data, enum rome_tlv_dnld_mode mode) + const u8 *data, enum qca_tlv_dnld_mode mode, + enum qca_btsoc_type soc_type) { struct sk_buff *skb; struct edl_event_hdr *edl; struct tlv_seg_resp *tlv_resp; u8 cmd[MAX_SIZE_PER_TLV_SEGMENT + 2]; int err = 0; + u8 event_type = HCI_EV_VENDOR; + u8 rlen = (sizeof(*edl) + sizeof(*tlv_resp)); + u8 rtype = EDL_TVL_DNLD_RES_EVT; cmd[0] = EDL_PATCH_TLV_REQ_CMD; cmd[1] = seg_size; memcpy(cmd + 2, data, seg_size); - if (mode == ROME_SKIP_EVT_VSE_CC || mode == ROME_SKIP_EVT_VSE) + if (mode == QCA_SKIP_EVT_VSE_CC || mode == QCA_SKIP_EVT_VSE) return __hci_cmd_send(hdev, EDL_PATCH_CMD_OPCODE, seg_size + 2, cmd); + /* Unlike other SoC's sending version command response as payload to + * VSE event. WCN3991 sends version command response as a payload to + * command complete event. + */ + if (soc_type == QCA_WCN3991) { + event_type = 0; + rlen = sizeof(*edl); + rtype = EDL_PATCH_TLV_REQ_CMD; + } + skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, seg_size + 2, cmd, - HCI_EV_VENDOR, HCI_INIT_TIMEOUT); + event_type, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { err = PTR_ERR(skb); bt_dev_err(hdev, "QCA Failed to send TLV segment (%d)", err); return err; } - if (skb->len != sizeof(*edl) + sizeof(*tlv_resp)) { + if (skb->len != rlen) { bt_dev_err(hdev, "QCA TLV response size mismatch"); err = -EILSEQ; goto out; @@ -260,13 +291,19 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, goto out; } - tlv_resp = (struct tlv_seg_resp *)(edl->data); + if (edl->cresp != EDL_CMD_REQ_RES_EVT || edl->rtype != rtype) { + bt_dev_err(hdev, "QCA TLV with error stat 0x%x rtype 0x%x", + edl->cresp, edl->rtype); + err = -EIO; + } - if (edl->cresp != EDL_CMD_REQ_RES_EVT || - edl->rtype != EDL_TVL_DNLD_RES_EVT || tlv_resp->result != 0x00) { + if (soc_type == QCA_WCN3991) + goto out; + + tlv_resp = (struct tlv_seg_resp *)(edl->data); + if (tlv_resp->result) { bt_dev_err(hdev, "QCA TLV with error stat 0x%x rtype 0x%x (0x%x)", edl->cresp, edl->rtype, tlv_resp->result); - err = -EIO; } out: @@ -301,7 +338,8 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev) } static int qca_download_firmware(struct hci_dev *hdev, - struct rome_config *config) + struct qca_fw_config *config, + enum qca_btsoc_type soc_type) { const struct firmware *fw; const u8 *segment; @@ -328,10 +366,10 @@ static int qca_download_firmware(struct hci_dev *hdev, remain -= segsize; /* The last segment is always acked regardless download mode */ if (!remain || segsize < MAX_SIZE_PER_TLV_SEGMENT) - config->dnld_mode = ROME_SKIP_EVT_NONE; + config->dnld_mode = QCA_SKIP_EVT_NONE; ret = qca_tlv_send_segment(hdev, segsize, segment, - config->dnld_mode); + config->dnld_mode, soc_type); if (ret) goto out; @@ -344,8 +382,8 @@ static int qca_download_firmware(struct hci_dev *hdev, * decrease the BT in initialization time. Here we will inject a command * complete event to avoid a command timeout error message. */ - if (config->dnld_type == ROME_SKIP_EVT_VSE_CC || - config->dnld_type == ROME_SKIP_EVT_VSE) + if (config->dnld_type == QCA_SKIP_EVT_VSE_CC || + config->dnld_type == QCA_SKIP_EVT_VSE) ret = qca_inject_cmd_complete_event(hdev); out: @@ -382,7 +420,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, enum qca_btsoc_type soc_type, u32 soc_ver, const char *firmware_name) { - struct rome_config config; + struct qca_fw_config config; int err; u8 rom_ver = 0; @@ -405,7 +443,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, "qca/rampatch_%08x.bin", soc_ver); } - err = qca_download_firmware(hdev, &config); + err = qca_download_firmware(hdev, &config, soc_type); if (err < 0) { bt_dev_err(hdev, "QCA Failed to download patch (%d)", err); return err; @@ -426,7 +464,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/nvm_%08x.bin", soc_ver); - err = qca_download_firmware(hdev, &config); + err = qca_download_firmware(hdev, &config, soc_type); if (err < 0) { bt_dev_err(hdev, "QCA Failed to download NVM (%d)", err); return err; diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 69c5315a65fd..f5795b1a3779 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -56,24 +56,24 @@ enum qca_baudrate { QCA_BAUDRATE_RESERVED }; -enum rome_tlv_dnld_mode { - ROME_SKIP_EVT_NONE, - ROME_SKIP_EVT_VSE, - ROME_SKIP_EVT_CC, - ROME_SKIP_EVT_VSE_CC +enum qca_tlv_dnld_mode { + QCA_SKIP_EVT_NONE, + QCA_SKIP_EVT_VSE, + QCA_SKIP_EVT_CC, + QCA_SKIP_EVT_VSE_CC }; -enum rome_tlv_type { +enum qca_tlv_type { TLV_TYPE_PATCH = 1, TLV_TYPE_NVM }; -struct rome_config { +struct qca_fw_config { u8 type; char fwname[64]; uint8_t user_baud_rate; - enum rome_tlv_dnld_mode dnld_mode; - enum rome_tlv_dnld_mode dnld_type; + enum qca_tlv_dnld_mode dnld_mode; + enum qca_tlv_dnld_mode dnld_type; }; struct edl_event_hdr { @@ -82,10 +82,10 @@ struct edl_event_hdr { __u8 data[0]; } __packed; -struct rome_version { +struct qca_btsoc_version { __le32 product_id; __le16 patch_ver; - __le16 rome_ver; + __le16 rom_ver; __le32 soc_id; } __packed; @@ -125,6 +125,7 @@ enum qca_btsoc_type { QCA_AR3002, QCA_ROME, QCA_WCN3990, + QCA_WCN3991, QCA_WCN3998, }; @@ -134,12 +135,14 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr); int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, enum qca_btsoc_type soc_type, u32 soc_ver, const char *firmware_name); -int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version); +int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version, + enum qca_btsoc_type); int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); int qca_send_pre_shutdown_cmd(struct hci_dev *hdev); static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) { - return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998; + return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3991 || + soc_type == QCA_WCN3998; } #else @@ -155,7 +158,8 @@ static inline int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, return -EOPNOTSUPP; } -static inline int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) +static inline int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version, + enum qca_btsoc_type) { return -EOPNOTSUPP; } diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index e3164c200eac..bbd290fbe4e3 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1262,7 +1262,7 @@ static int qca_setup(struct hci_uart *hu) if (ret) return ret; - ret = qca_read_soc_version(hdev, &soc_ver); + ret = qca_read_soc_version(hdev, &soc_ver, soc_type); if (ret) return ret; } else { @@ -1282,7 +1282,7 @@ static int qca_setup(struct hci_uart *hu) if (!qca_is_wcn399x(soc_type)) { /* Get QCA version information */ - ret = qca_read_soc_version(hdev, &soc_ver); + ret = qca_read_soc_version(hdev, &soc_ver, soc_type); if (ret) return ret; } @@ -1340,6 +1340,17 @@ static const struct qca_vreg_data qca_soc_data_wcn3990 = { .num_vregs = 4, }; +static const struct qca_vreg_data qca_soc_data_wcn3991 = { + .soc_type = QCA_WCN3991, + .vregs = (struct qca_vreg []) { + { "vddio", 15000 }, + { "vddxo", 80000 }, + { "vddrf", 300000 }, + { "vddch0", 450000 }, + }, + .num_vregs = 4, +}; + static const struct qca_vreg_data qca_soc_data_wcn3998 = { .soc_type = QCA_WCN3998, .vregs = (struct qca_vreg []) { @@ -1567,6 +1578,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,qca6174-bt" }, { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, + { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991}, { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, { /* sentinel */ } }; diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index a0cecb12b6f9..f0bc0841cbc4 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1406,7 +1406,7 @@ static void sysc_init_revision_quirks(struct sysc *ddata) } /* 1-wire needs module's internal clocks enabled for reset */ -static void sysc_clk_enable_quirk_hdq1w(struct sysc *ddata) +static void sysc_pre_reset_quirk_hdq1w(struct sysc *ddata) { int offset = 0x0c; /* HDQ_CTRL_STATUS */ u16 val; @@ -1494,7 +1494,7 @@ static void sysc_init_module_quirks(struct sysc *ddata) return; if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) { - ddata->clk_enable_quirk = sysc_clk_enable_quirk_hdq1w; + ddata->clk_disable_quirk = sysc_pre_reset_quirk_hdq1w; return; } diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c index c78127ccbc0d..638c693e17ad 100644 --- a/drivers/char/ipmi/ipmi_si_platform.c +++ b/drivers/char/ipmi/ipmi_si_platform.c @@ -194,7 +194,7 @@ static int platform_ipmi_probe(struct platform_device *pdev) else io.slave_addr = slave_addr; - io.irq = platform_get_irq(pdev, 0); + io.irq = platform_get_irq_optional(pdev, 0); if (io.irq > 0) io.irq_setup = ipmi_std_irq_setup; else @@ -378,7 +378,7 @@ static int acpi_ipmi_probe(struct platform_device *pdev) io.irq = tmp; io.irq_setup = acpi_gpe_irq_setup; } else { - int irq = platform_get_irq(pdev, 0); + int irq = platform_get_irq_optional(pdev, 0); if (irq > 0) { io.irq = irq; diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index fbef740704d0..b8b2072742a5 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -43,12 +43,12 @@ struct imx_sc_msg_req_set_clock_rate { __le32 rate; __le16 resource; u8 clk; -} __packed; +} __packed __aligned(4); struct req_get_clock_rate { __le16 resource; u8 clk; -} __packed; +} __packed __aligned(4); struct resp_get_clock_rate { __le32 rate; @@ -84,7 +84,7 @@ struct imx_sc_msg_get_clock_parent { struct req_get_clock_parent { __le16 resource; u8 clk; - } __packed req; + } __packed __aligned(4) req; struct resp_get_clock_parent { u8 parent; } resp; @@ -121,7 +121,7 @@ struct imx_sc_msg_req_clock_enable { u8 clk; u8 enable; u8 autog; -} __packed; +} __packed __aligned(4); static inline struct clk_scu *to_clk_scu(struct clk_hw *hw) { diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c index 2782d91838ac..2cca1ced913d 100644 --- a/drivers/clk/ti/clk-43xx.c +++ b/drivers/clk/ti/clk-43xx.c @@ -78,7 +78,7 @@ static const struct omap_clkctrl_reg_data am4_gfx_l3_clkctrl_regs[] __initconst }; static const struct omap_clkctrl_reg_data am4_l4_rtc_clkctrl_regs[] __initconst = { - { AM4_L4_RTC_RTC_CLKCTRL, NULL, CLKF_SW_SUP, "clk_32768_ck" }, + { AM4_L4_RTC_RTC_CLKCTRL, NULL, CLKF_SW_SUP, "clkdiv32k_ick" }, { 0 }, }; diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index 2317d4e3daaf..36933e2b3b0d 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -233,7 +233,8 @@ static u64 notrace read_hv_clock_tsc(struct clocksource *arg) static u64 read_hv_sched_clock_tsc(void) { - return read_hv_clock_tsc(NULL) - hv_sched_clock_offset; + return (read_hv_clock_tsc(NULL) - hv_sched_clock_offset) * + (NSEC_PER_SEC / HV_CLOCK_HZ); } static struct clocksource hyperv_cs_tsc = { @@ -258,7 +259,8 @@ static u64 notrace read_hv_clock_msr(struct clocksource *arg) static u64 read_hv_sched_clock_msr(void) { - return read_hv_clock_msr(NULL) - hv_sched_clock_offset; + return (read_hv_clock_msr(NULL) - hv_sched_clock_offset) * + (NSEC_PER_SEC / HV_CLOCK_HZ); } static struct clocksource hyperv_cs_msr = { diff --git a/drivers/cpufreq/cpufreq_times.c b/drivers/cpufreq/cpufreq_times.c index 5b5248a7c87c..4df55b323fc1 100644 --- a/drivers/cpufreq/cpufreq_times.c +++ b/drivers/cpufreq/cpufreq_times.c @@ -15,36 +15,14 @@ #include #include -#include -#include #include -#include #include #include #include #include #include -#define UID_HASH_BITS 10 - -static DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS); - static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */ -static DEFINE_SPINLOCK(uid_lock); /* uid_hash_table */ - -struct concurrent_times { - atomic64_t active[NR_CPUS]; - atomic64_t policy[NR_CPUS]; -}; - -struct uid_entry { - uid_t uid; - unsigned int max_state; - struct hlist_node hash; - struct rcu_head rcu; - struct concurrent_times *concurrent_times; - u64 time_in_state[0]; -}; /** * struct cpu_freqs - per-cpu frequency information @@ -64,248 +42,6 @@ static struct cpu_freqs *all_freqs[NR_CPUS]; static unsigned int next_offset; - -/* Caller must hold rcu_read_lock() */ -static struct uid_entry *find_uid_entry_rcu(uid_t uid) -{ - struct uid_entry *uid_entry; - - hash_for_each_possible_rcu(uid_hash_table, uid_entry, hash, uid) { - if (uid_entry->uid == uid) - return uid_entry; - } - return NULL; -} - -/* Caller must hold uid lock */ -static struct uid_entry *find_uid_entry_locked(uid_t uid) -{ - struct uid_entry *uid_entry; - - hash_for_each_possible(uid_hash_table, uid_entry, hash, uid) { - if (uid_entry->uid == uid) - return uid_entry; - } - return NULL; -} - -/* Caller must hold uid lock */ -static struct uid_entry *find_or_register_uid_locked(uid_t uid) -{ - struct uid_entry *uid_entry, *temp; - struct concurrent_times *times; - unsigned int max_state = READ_ONCE(next_offset); - size_t alloc_size = sizeof(*uid_entry) + max_state * - sizeof(uid_entry->time_in_state[0]); - - uid_entry = find_uid_entry_locked(uid); - if (uid_entry) { - if (uid_entry->max_state == max_state) - return uid_entry; - /* uid_entry->time_in_state is too small to track all freqs, so - * expand it. - */ - temp = __krealloc(uid_entry, alloc_size, GFP_ATOMIC); - if (!temp) - return uid_entry; - temp->max_state = max_state; - memset(temp->time_in_state + uid_entry->max_state, 0, - (max_state - uid_entry->max_state) * - sizeof(uid_entry->time_in_state[0])); - if (temp != uid_entry) { - hlist_replace_rcu(&uid_entry->hash, &temp->hash); - kfree_rcu(uid_entry, rcu); - } - return temp; - } - - uid_entry = kzalloc(alloc_size, GFP_ATOMIC); - if (!uid_entry) - return NULL; - times = kzalloc(sizeof(*times), GFP_ATOMIC); - if (!times) { - kfree(uid_entry); - return NULL; - } - - uid_entry->uid = uid; - uid_entry->max_state = max_state; - uid_entry->concurrent_times = times; - - hash_add_rcu(uid_hash_table, &uid_entry->hash, uid); - - return uid_entry; -} - -static int single_uid_time_in_state_show(struct seq_file *m, void *ptr) -{ - struct uid_entry *uid_entry; - unsigned int i; - uid_t uid = from_kuid_munged(current_user_ns(), *(kuid_t *)m->private); - - if (uid == overflowuid) - return -EINVAL; - - rcu_read_lock(); - - uid_entry = find_uid_entry_rcu(uid); - if (!uid_entry) { - rcu_read_unlock(); - return 0; - } - - for (i = 0; i < uid_entry->max_state; ++i) { - u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]); - seq_write(m, &time, sizeof(time)); - } - - rcu_read_unlock(); - - return 0; -} - -static void *uid_seq_start(struct seq_file *seq, loff_t *pos) -{ - if (*pos >= HASH_SIZE(uid_hash_table)) - return NULL; - - return &uid_hash_table[*pos]; -} - -static void *uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - do { - (*pos)++; - - if (*pos >= HASH_SIZE(uid_hash_table)) - return NULL; - } while (hlist_empty(&uid_hash_table[*pos])); - - return &uid_hash_table[*pos]; -} - -static void uid_seq_stop(struct seq_file *seq, void *v) { } - -static int uid_time_in_state_seq_show(struct seq_file *m, void *v) -{ - struct uid_entry *uid_entry; - struct cpu_freqs *freqs, *last_freqs = NULL; - int i, cpu; - - if (v == uid_hash_table) { - seq_puts(m, "uid:"); - for_each_possible_cpu(cpu) { - freqs = all_freqs[cpu]; - if (!freqs || freqs == last_freqs) - continue; - last_freqs = freqs; - for (i = 0; i < freqs->max_state; i++) { - seq_put_decimal_ull(m, " ", - freqs->freq_table[i]); - } - } - seq_putc(m, '\n'); - } - - rcu_read_lock(); - - hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { - if (uid_entry->max_state) { - seq_put_decimal_ull(m, "", uid_entry->uid); - seq_putc(m, ':'); - } - for (i = 0; i < uid_entry->max_state; ++i) { - u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]); - seq_put_decimal_ull(m, " ", time); - } - if (uid_entry->max_state) - seq_putc(m, '\n'); - } - - rcu_read_unlock(); - return 0; -} - -static int concurrent_time_seq_show(struct seq_file *m, void *v, - atomic64_t *(*get_times)(struct concurrent_times *)) -{ - struct uid_entry *uid_entry; - int i, num_possible_cpus = num_possible_cpus(); - - rcu_read_lock(); - - hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) { - atomic64_t *times = get_times(uid_entry->concurrent_times); - - seq_put_decimal_ull(m, "", (u64)uid_entry->uid); - seq_putc(m, ':'); - - for (i = 0; i < num_possible_cpus; ++i) { - u64 time = nsec_to_clock_t(atomic64_read(×[i])); - - seq_put_decimal_ull(m, " ", time); - } - seq_putc(m, '\n'); - } - - rcu_read_unlock(); - - return 0; -} - -static inline atomic64_t *get_active_times(struct concurrent_times *times) -{ - return times->active; -} - -static int concurrent_active_time_seq_show(struct seq_file *m, void *v) -{ - if (v == uid_hash_table) { - seq_put_decimal_ull(m, "cpus: ", num_possible_cpus()); - seq_putc(m, '\n'); - } - - return concurrent_time_seq_show(m, v, get_active_times); -} - -static inline atomic64_t *get_policy_times(struct concurrent_times *times) -{ - return times->policy; -} - -static int concurrent_policy_time_seq_show(struct seq_file *m, void *v) -{ - int i; - struct cpu_freqs *freqs, *last_freqs = NULL; - - if (v == uid_hash_table) { - int cnt = 0; - - for_each_possible_cpu(i) { - freqs = all_freqs[i]; - if (!freqs) - continue; - if (freqs != last_freqs) { - if (last_freqs) { - seq_put_decimal_ull(m, ": ", cnt); - seq_putc(m, ' '); - cnt = 0; - } - seq_put_decimal_ull(m, "policy", i); - - last_freqs = freqs; - } - cnt++; - } - if (last_freqs) { - seq_put_decimal_ull(m, ": ", cnt); - seq_putc(m, '\n'); - } - } - - return concurrent_time_seq_show(m, v, get_policy_times); -} - void cpufreq_task_times_init(struct task_struct *p) { unsigned long flags; @@ -398,14 +134,7 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime) { unsigned long flags; unsigned int state; - unsigned int active_cpu_cnt = 0; - unsigned int policy_cpu_cnt = 0; - unsigned int policy_first_cpu; - struct uid_entry *uid_entry; struct cpu_freqs *freqs = all_freqs[task_cpu(p)]; - struct cpufreq_policy *policy; - uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p)); - int cpu = 0; if (!freqs || is_idle_task(p) || p->flags & PF_EXITING) return; @@ -417,48 +146,6 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime) p->time_in_state) p->time_in_state[state] += cputime; spin_unlock_irqrestore(&task_time_in_state_lock, flags); - - spin_lock_irqsave(&uid_lock, flags); - uid_entry = find_or_register_uid_locked(uid); - if (uid_entry && state < uid_entry->max_state) - uid_entry->time_in_state[state] += cputime; - spin_unlock_irqrestore(&uid_lock, flags); - - rcu_read_lock(); - uid_entry = find_uid_entry_rcu(uid); - if (!uid_entry) { - rcu_read_unlock(); - return; - } - - for_each_possible_cpu(cpu) - if (!idle_cpu(cpu)) - ++active_cpu_cnt; - - atomic64_add(cputime, - &uid_entry->concurrent_times->active[active_cpu_cnt - 1]); - - policy = cpufreq_cpu_get(task_cpu(p)); - if (!policy) { - /* - * This CPU may have just come up and not have a cpufreq policy - * yet. - */ - rcu_read_unlock(); - return; - } - - for_each_cpu(cpu, policy->related_cpus) - if (!idle_cpu(cpu)) - ++policy_cpu_cnt; - - policy_first_cpu = cpumask_first(policy->related_cpus); - cpufreq_cpu_put(policy); - - atomic64_add(cputime, - &uid_entry->concurrent_times->policy[policy_first_cpu + - policy_cpu_cnt - 1]); - rcu_read_unlock(); } static int cpufreq_times_get_index(struct cpu_freqs *freqs, unsigned int freq) @@ -510,35 +197,6 @@ void cpufreq_times_create_policy(struct cpufreq_policy *policy) all_freqs[cpu] = freqs; } -static void uid_entry_reclaim(struct rcu_head *rcu) -{ - struct uid_entry *uid_entry = container_of(rcu, struct uid_entry, rcu); - - kfree(uid_entry->concurrent_times); - kfree(uid_entry); -} - -void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end) -{ - struct uid_entry *uid_entry; - struct hlist_node *tmp; - unsigned long flags; - - spin_lock_irqsave(&uid_lock, flags); - - for (; uid_start <= uid_end; uid_start++) { - hash_for_each_possible_safe(uid_hash_table, uid_entry, tmp, - hash, uid_start) { - if (uid_start == uid_entry->uid) { - hash_del_rcu(&uid_entry->hash); - call_rcu(&uid_entry->rcu, uid_entry_reclaim); - } - } - } - - spin_unlock_irqrestore(&uid_lock, flags); -} - void cpufreq_times_record_transition(struct cpufreq_policy *policy, unsigned int new_freq) { @@ -551,82 +209,3 @@ void cpufreq_times_record_transition(struct cpufreq_policy *policy, if (index >= 0) WRITE_ONCE(freqs->last_index, index); } - -static const struct seq_operations uid_time_in_state_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = uid_time_in_state_seq_show, -}; - -static int uid_time_in_state_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &uid_time_in_state_seq_ops); -} - -int single_uid_time_in_state_open(struct inode *inode, struct file *file) -{ - return single_open(file, single_uid_time_in_state_show, - &(inode->i_uid)); -} - -static const struct file_operations uid_time_in_state_fops = { - .open = uid_time_in_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct seq_operations concurrent_active_time_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = concurrent_active_time_seq_show, -}; - -static int concurrent_active_time_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &concurrent_active_time_seq_ops); -} - -static const struct file_operations concurrent_active_time_fops = { - .open = concurrent_active_time_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static const struct seq_operations concurrent_policy_time_seq_ops = { - .start = uid_seq_start, - .next = uid_seq_next, - .stop = uid_seq_stop, - .show = concurrent_policy_time_seq_show, -}; - -static int concurrent_policy_time_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &concurrent_policy_time_seq_ops); -} - -static const struct file_operations concurrent_policy_time_fops = { - .open = concurrent_policy_time_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init cpufreq_times_init(void) -{ - proc_create_data("uid_time_in_state", 0444, NULL, - &uid_time_in_state_fops, NULL); - - proc_create_data("uid_concurrent_active_time", 0444, NULL, - &concurrent_active_time_fops, NULL); - - proc_create_data("uid_concurrent_policy_time", 0444, NULL, - &concurrent_policy_time_fops, NULL); - - return 0; -} - -early_initcall(cpufreq_times_init); diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 2384924e8abe..6ab34ae893aa 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -111,6 +111,7 @@ static int dma_buf_release(struct inode *inode, struct file *file) dma_resv_fini(dmabuf->resv); module_put(dmabuf->owner); + kfree(dmabuf->name); kfree(msm_dma_buf); return 0; } diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index e51d836afcc7..1092d4ce723e 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -1947,8 +1947,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc) return; } - spin_lock(&cohc->lock); - /* * When we reach this point, at least one queue item * should have been moved over from cohc->queue to @@ -1969,8 +1967,6 @@ static void dma_tc_handle(struct coh901318_chan *cohc) if (coh901318_queue_start(cohc) == NULL) cohc->busy = 0; - spin_unlock(&cohc->lock); - /* * This tasklet will remove items from cohc->active * and thus terminates them. diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index c27e206a764c..67736c801f3c 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1328,13 +1328,14 @@ static void sdma_free_chan_resources(struct dma_chan *chan) sdma_channel_synchronize(chan); - if (sdmac->event_id0) + if (sdmac->event_id0 >= 0) sdma_event_disable(sdmac, sdmac->event_id0); if (sdmac->event_id1) sdma_event_disable(sdmac, sdmac->event_id1); sdmac->event_id0 = 0; sdmac->event_id1 = 0; + sdmac->context_loaded = false; sdma_set_channel_priority(sdmac, 0); @@ -1628,7 +1629,7 @@ static int sdma_config(struct dma_chan *chan, memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg)); /* Set ENBLn earlier to make sure dma request triggered after that */ - if (sdmac->event_id0) { + if (sdmac->event_id0 >= 0) { if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events) return -EINVAL; sdma_event_enable(sdmac, sdmac->event_id0); diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 3a45079d11ec..4a750e29bfb5 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -281,7 +281,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get( /* Do not allocate if desc are waiting for ack */ list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) { - if (async_tx_test_ack(&dma_desc->txd)) { + if (async_tx_test_ack(&dma_desc->txd) && !dma_desc->cb_count) { list_del(&dma_desc->node); spin_unlock_irqrestore(&tdc->lock, flags); dma_desc->txd.flags = 0; @@ -756,10 +756,6 @@ static int tegra_dma_terminate_all(struct dma_chan *dc) bool was_busy; spin_lock_irqsave(&tdc->lock, flags); - if (list_empty(&tdc->pending_sg_req)) { - spin_unlock_irqrestore(&tdc->lock, flags); - return 0; - } if (!tdc->busy) goto skip_dma_stop; diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c index 2d263382d797..880ffd833718 100644 --- a/drivers/edac/synopsys_edac.c +++ b/drivers/edac/synopsys_edac.c @@ -479,20 +479,14 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) pinf = &p->ceinfo; if (!priv->p_data->quirks) { snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "DDR ECC error type:%s Row %d Bank %d Col %d ", - "CE", pinf->row, pinf->bank, pinf->col); - snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "Bit Position: %d Data: 0x%08x\n", + "DDR ECC error type:%s Row %d Bank %d Col %d Bit Position: %d Data: 0x%08x", + "CE", pinf->row, pinf->bank, pinf->col, pinf->bitpos, pinf->data); } else { snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "DDR ECC error type:%s Row %d Bank %d Col %d ", - "CE", pinf->row, pinf->bank, pinf->col); - snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "BankGroup Number %d Block Number %d ", - pinf->bankgrpnr, pinf->blknr); - snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "Bit Position: %d Data: 0x%08x\n", + "DDR ECC error type:%s Row %d Bank %d Col %d BankGroup Number %d Block Number %d Bit Position: %d Data: 0x%08x", + "CE", pinf->row, pinf->bank, pinf->col, + pinf->bankgrpnr, pinf->blknr, pinf->bitpos, pinf->data); } @@ -509,10 +503,8 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p) "UE", pinf->row, pinf->bank, pinf->col); } else { snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "DDR ECC error type :%s Row %d Bank %d Col %d ", - "UE", pinf->row, pinf->bank, pinf->col); - snprintf(priv->message, SYNPS_EDAC_MSG_SIZE, - "BankGroup Number %d Block Number %d", + "DDR ECC error type :%s Row %d Bank %d Col %d BankGroup Number %d Block Number %d", + "UE", pinf->row, pinf->bank, pinf->col, pinf->bankgrpnr, pinf->blknr); } diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 34d41f67b54d..ad8a4bc074fb 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -544,7 +544,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, seed = early_memremap(efi.rng_seed, sizeof(*seed)); if (seed != NULL) { - size = seed->size; + size = READ_ONCE(seed->size); early_memunmap(seed, sizeof(*seed)); } else { pr_err("Could not map UEFI random seed!\n"); @@ -554,7 +554,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, sizeof(*seed) + size); if (seed != NULL) { pr_notice("seeding entropy pool\n"); - add_bootloader_randomness(seed->bits, seed->size); + add_bootloader_randomness(seed->bits, size); early_memunmap(seed, sizeof(*seed) + size); } else { pr_err("Could not map UEFI random seed!\n"); diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 7576450c8254..aff3dfb4d7ba 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -83,13 +83,16 @@ static ssize_t efivar_attr_read(struct efivar_entry *entry, char *buf) { struct efi_variable *var = &entry->var; + unsigned long size = sizeof(var->Data); char *str = buf; + int ret; if (!entry || !buf) return -EINVAL; - var->DataSize = 1024; - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) + ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); + var->DataSize = size; + if (ret) return -EIO; if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) @@ -116,13 +119,16 @@ static ssize_t efivar_size_read(struct efivar_entry *entry, char *buf) { struct efi_variable *var = &entry->var; + unsigned long size = sizeof(var->Data); char *str = buf; + int ret; if (!entry || !buf) return -EINVAL; - var->DataSize = 1024; - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) + ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); + var->DataSize = size; + if (ret) return -EIO; str += sprintf(str, "0x%lx\n", var->DataSize); @@ -133,12 +139,15 @@ static ssize_t efivar_data_read(struct efivar_entry *entry, char *buf) { struct efi_variable *var = &entry->var; + unsigned long size = sizeof(var->Data); + int ret; if (!entry || !buf) return -EINVAL; - var->DataSize = 1024; - if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data)) + ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data); + var->DataSize = size; + if (ret) return -EIO; memcpy(buf, var->Data, var->DataSize); @@ -199,6 +208,9 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) u8 *data; int err; + if (!entry || !buf) + return -EINVAL; + if (in_compat_syscall()) { struct compat_efi_variable *compat; @@ -250,14 +262,16 @@ efivar_show_raw(struct efivar_entry *entry, char *buf) { struct efi_variable *var = &entry->var; struct compat_efi_variable *compat; + unsigned long datasize = sizeof(var->Data); size_t size; + int ret; if (!entry || !buf) return 0; - var->DataSize = 1024; - if (efivar_entry_get(entry, &entry->var.Attributes, - &entry->var.DataSize, entry->var.Data)) + ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data); + var->DataSize = datasize; + if (ret) return -EIO; if (in_compat_syscall()) { diff --git a/drivers/firmware/imx/imx-scu.c b/drivers/firmware/imx/imx-scu.c index 04a24a863d6e..35a5f8f8eea5 100644 --- a/drivers/firmware/imx/imx-scu.c +++ b/drivers/firmware/imx/imx-scu.c @@ -29,6 +29,7 @@ struct imx_sc_chan { struct mbox_client cl; struct mbox_chan *ch; int idx; + struct completion tx_done; }; struct imx_sc_ipc { @@ -100,6 +101,14 @@ int imx_scu_get_handle(struct imx_sc_ipc **ipc) } EXPORT_SYMBOL(imx_scu_get_handle); +/* Callback called when the word of a message is ack-ed, eg read by SCU */ +static void imx_scu_tx_done(struct mbox_client *cl, void *mssg, int r) +{ + struct imx_sc_chan *sc_chan = container_of(cl, struct imx_sc_chan, cl); + + complete(&sc_chan->tx_done); +} + static void imx_scu_rx_callback(struct mbox_client *c, void *msg) { struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl); @@ -143,6 +152,19 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg) for (i = 0; i < hdr->size; i++) { sc_chan = &sc_ipc->chans[i % 4]; + + /* + * SCU requires that all messages words are written + * sequentially but linux MU driver implements multiple + * independent channels for each register so ordering between + * different channels must be ensured by SCU API interface. + * + * Wait for tx_done before every send to ensure that no + * queueing happens at the mailbox channel level. + */ + wait_for_completion(&sc_chan->tx_done); + reinit_completion(&sc_chan->tx_done); + ret = mbox_send_message(sc_chan->ch, &data[i]); if (ret < 0) return ret; @@ -225,6 +247,11 @@ static int imx_scu_probe(struct platform_device *pdev) cl->knows_txdone = true; cl->rx_callback = imx_scu_rx_callback; + /* Initial tx_done completion as "done" */ + cl->tx_done = imx_scu_tx_done; + init_completion(&sc_chan->tx_done); + complete(&sc_chan->tx_done); + sc_chan->sc_ipc = sc_ipc; sc_chan->idx = i % 4; sc_chan->ch = mbox_request_channel_byname(cl, chan_name); diff --git a/drivers/firmware/imx/misc.c b/drivers/firmware/imx/misc.c index 4b56a587dacd..d073cb3ce699 100644 --- a/drivers/firmware/imx/misc.c +++ b/drivers/firmware/imx/misc.c @@ -16,7 +16,7 @@ struct imx_sc_msg_req_misc_set_ctrl { u32 ctrl; u32 val; u16 resource; -} __packed; +} __packed __aligned(4); struct imx_sc_msg_req_cpu_start { struct imx_sc_rpc_msg hdr; @@ -24,18 +24,18 @@ struct imx_sc_msg_req_cpu_start { u32 address_lo; u16 resource; u8 enable; -} __packed; +} __packed __aligned(4); struct imx_sc_msg_req_misc_get_ctrl { struct imx_sc_rpc_msg hdr; u32 ctrl; u16 resource; -} __packed; +} __packed __aligned(4); struct imx_sc_msg_resp_misc_get_ctrl { struct imx_sc_rpc_msg hdr; u32 val; -} __packed; +} __packed __aligned(4); /* * This function sets a miscellaneous control value. diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index b556612207e5..af3ae0087de4 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -61,7 +61,7 @@ struct imx_sc_msg_req_set_resource_power_mode { struct imx_sc_rpc_msg hdr; u16 resource; u8 mode; -} __packed; +} __packed __aligned(4); #define IMX_SCU_PD_NAME_SIZE 20 struct imx_sc_pm_domain { diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 1f98e988c0d3..b2e186047014 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -21,18 +21,21 @@ #include "gpiolib.h" #include "gpiolib-acpi.h" -#define QUIRK_NO_EDGE_EVENTS_ON_BOOT 0x01l -#define QUIRK_NO_WAKEUP 0x02l - static int run_edge_events_on_boot = -1; module_param(run_edge_events_on_boot, int, 0444); MODULE_PARM_DESC(run_edge_events_on_boot, "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto"); -static int honor_wakeup = -1; -module_param(honor_wakeup, int, 0444); -MODULE_PARM_DESC(honor_wakeup, - "Honor the ACPI wake-capable flag: 0=no, 1=yes, -1=auto"); +static char *ignore_wake; +module_param(ignore_wake, charp, 0444); +MODULE_PARM_DESC(ignore_wake, + "controller@pin combos on which to ignore the ACPI wake flag " + "ignore_wake=controller@pin[,controller@pin[,...]]"); + +struct acpi_gpiolib_dmi_quirk { + bool no_edge_events_on_boot; + char *ignore_wake; +}; /** * struct acpi_gpio_event - ACPI GPIO event handler data @@ -202,6 +205,57 @@ static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio) acpi_gpiochip_request_irq(acpi_gpio, event); } +static bool acpi_gpio_in_ignore_list(const char *controller_in, int pin_in) +{ + const char *controller, *pin_str; + int len, pin; + char *endp; + + controller = ignore_wake; + while (controller) { + pin_str = strchr(controller, '@'); + if (!pin_str) + goto err; + + len = pin_str - controller; + if (len == strlen(controller_in) && + strncmp(controller, controller_in, len) == 0) { + pin = simple_strtoul(pin_str + 1, &endp, 10); + if (*endp != 0 && *endp != ',') + goto err; + + if (pin == pin_in) + return true; + } + + controller = strchr(controller, ','); + if (controller) + controller++; + } + + return false; +err: + pr_err_once("Error invalid value for gpiolib_acpi.ignore_wake: %s\n", + ignore_wake); + return false; +} + +static bool acpi_gpio_irq_is_wake(struct device *parent, + struct acpi_resource_gpio *agpio) +{ + int pin = agpio->pin_table[0]; + + if (agpio->wake_capable != ACPI_WAKE_CAPABLE) + return false; + + if (acpi_gpio_in_ignore_list(dev_name(parent), pin)) { + dev_info(parent, "Ignoring wakeup on pin %d\n", pin); + return false; + } + + return true; +} + static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, void *context) { @@ -282,7 +336,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, event->handle = evt_handle; event->handler = handler; event->irq = irq; - event->irq_is_wake = honor_wakeup && agpio->wake_capable == ACPI_WAKE_CAPABLE; + event->irq_is_wake = acpi_gpio_irq_is_wake(chip->parent, agpio); event->pin = pin; event->desc = desc; @@ -1321,7 +1375,9 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "MINIX"), DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"), }, - .driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .no_edge_events_on_boot = true, + }, }, { /* @@ -1334,16 +1390,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"), DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"), }, - .driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .no_edge_events_on_boot = true, + }, }, { /* - * Various HP X2 10 Cherry Trail models use an external - * embedded-controller connected via I2C + an ACPI GPIO - * event handler. The embedded controller generates various - * spurious wakeup events when suspended. So disable wakeup - * for its handler (it uses the only ACPI GPIO event handler). - * This breaks wakeup when opening the lid, the user needs + * HP X2 10 models with Cherry Trail SoC + TI PMIC use an + * external embedded-controller connected via I2C + an ACPI GPIO + * event handler on INT33FF:01 pin 0, causing spurious wakeups. + * When suspending by closing the LID, the power to the USB + * keyboard is turned off, causing INT0002 ACPI events to + * trigger once the XHCI controller notices the keyboard is + * gone. So INT0002 events cause spurious wakeups too. Ignoring + * EC wakes breaks wakeup when opening the lid, the user needs * to press the power-button to wakeup the system. The * alternative is suspend simply not working, which is worse. */ @@ -1351,33 +1411,61 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = { DMI_MATCH(DMI_SYS_VENDOR, "HP"), DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"), }, - .driver_data = (void *)QUIRK_NO_WAKEUP, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_wake = "INT33FF:01@0,INT0002:00@2", + }, + }, + { + /* + * HP X2 10 models with Bay Trail SoC + AXP288 PMIC use an + * external embedded-controller connected via I2C + an ACPI GPIO + * event handler on INT33FC:02 pin 28, causing spurious wakeups. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_MATCH(DMI_BOARD_NAME, "815D"), + }, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_wake = "INT33FC:02@28", + }, + }, + { + /* + * HP X2 10 models with Cherry Trail SoC + AXP288 PMIC use an + * external embedded-controller connected via I2C + an ACPI GPIO + * event handler on INT33FF:01 pin 0, causing spurious wakeups. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_MATCH(DMI_BOARD_NAME, "813E"), + }, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_wake = "INT33FF:01@0", + }, }, {} /* Terminating entry */ }; static int acpi_gpio_setup_params(void) { + const struct acpi_gpiolib_dmi_quirk *quirk = NULL; const struct dmi_system_id *id; - long quirks = 0; id = dmi_first_match(gpiolib_acpi_quirks); if (id) - quirks = (long)id->driver_data; + quirk = id->driver_data; if (run_edge_events_on_boot < 0) { - if (quirks & QUIRK_NO_EDGE_EVENTS_ON_BOOT) + if (quirk && quirk->no_edge_events_on_boot) run_edge_events_on_boot = 0; else run_edge_events_on_boot = 1; } - if (honor_wakeup < 0) { - if (quirks & QUIRK_NO_WAKEUP) - honor_wakeup = 0; - else - honor_wakeup = 1; - } + if (ignore_wake == NULL && quirk && quirk->ignore_wake) + ignore_wake = quirk->ignore_wake; return 0; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 484fa6560adc..a8cf55eb54d8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2194,9 +2194,16 @@ static void gpiochip_irq_disable(struct irq_data *d) { struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + /* + * Since we override .irq_disable() we need to mimic the + * behaviour of __irq_disable() in irq/chip.c. + * First call .irq_disable() if it exists, else mimic the + * behaviour of mask_irq() which calls .irq_mask() if + * it exists. + */ if (chip->irq.irq_disable) chip->irq.irq_disable(d); - else + else if (chip->irq.chip->irq_mask) chip->irq.chip->irq_mask(d); gpiochip_disable_irq(chip, d->hwirq); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index f2f40f05fa5c..c687432da426 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -365,8 +365,7 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * router.ddc_valid = false; router.cd_valid = false; for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) { - uint8_t grph_obj_type= - grph_obj_type = + uint8_t grph_obj_type = (le16_to_cpu(path->usGraphicObjIds[j]) & OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 81842ba8cd75..1e25ca34d876 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -694,11 +694,11 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, ssize_t result = 0; uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; - if (size & 3 || *pos & 3) + if (size > 4096 || size & 3 || *pos & 3) return -EINVAL; /* decode offset */ - offset = *pos & GENMASK_ULL(11, 0); + offset = (*pos & GENMASK_ULL(11, 0)) >> 2; se = (*pos & GENMASK_ULL(19, 12)) >> 12; sh = (*pos & GENMASK_ULL(27, 20)) >> 20; cu = (*pos & GENMASK_ULL(35, 28)) >> 28; @@ -729,7 +729,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, while (size) { uint32_t value; - value = data[offset++]; + value = data[result >> 2]; r = put_user(value, (uint32_t *)buf); if (r) { result = r; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 2816d0329738..14417cebe38b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3555,6 +3555,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) /* reset ring buffer */ ring->wptr = 0; + atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0); amdgpu_ring_clear_ring(ring); } else { amdgpu_ring_clear_ring(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index d85e1e559c82..40034efa64bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3756,6 +3756,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) /* reset ring buffer */ ring->wptr = 0; + atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0); amdgpu_ring_clear_ring(ring); } else { amdgpu_ring_clear_ring(ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index a7ba4c6cf7a1..f642e066e67a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -230,7 +230,8 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, unsigned int vmhub, uint32_t flush_type) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; - u32 tmp = gmc_v10_0_get_invalidate_req(vmid, flush_type); + u32 inv_req = gmc_v10_0_get_invalidate_req(vmid, flush_type); + u32 tmp; /* Use register 17 for GART */ const unsigned eng = 17; unsigned int i; @@ -258,7 +259,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n"); } - WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp); + WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, inv_req); /* * Issue a dummy read to wait for the ACK register to be cleared diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index da53a55bf955..688111ef814d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -487,13 +487,13 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, { bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub); const unsigned eng = 17; - u32 j, tmp; + u32 j, inv_req, tmp; struct amdgpu_vmhub *hub; BUG_ON(vmhub >= adev->num_vmhubs); hub = &adev->vmhub[vmhub]; - tmp = gmc_v9_0_get_invalidate_req(vmid, flush_type); + inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type); /* This is necessary for a HW workaround under SRIOV as well * as GFXOFF under bare metal @@ -504,7 +504,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, uint32_t req = hub->vm_inv_eng0_req + eng; uint32_t ack = hub->vm_inv_eng0_ack + eng; - amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, tmp, + amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req, 1 << vmid); return; } @@ -532,7 +532,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n"); } - WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp); + WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, inv_req); /* * Issue a dummy read to wait for the ACK register to be cleared diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 80934ca17260..c086262cc181 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -84,6 +84,13 @@ #define HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK 0x00010000L #define HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK 0x00020000L #define mmHDP_MEM_POWER_CTRL_BASE_IDX 0 + +/* for Vega20/arcturus regiter offset change */ +#define mmROM_INDEX_VG20 0x00e4 +#define mmROM_INDEX_VG20_BASE_IDX 0 +#define mmROM_DATA_VG20 0x00e5 +#define mmROM_DATA_VG20_BASE_IDX 0 + /* * Indirect registers accessor */ @@ -304,6 +311,8 @@ static bool soc15_read_bios_from_rom(struct amdgpu_device *adev, { u32 *dw_ptr; u32 i, length_dw; + uint32_t rom_index_offset; + uint32_t rom_data_offset; if (bios == NULL) return false; @@ -316,11 +325,23 @@ static bool soc15_read_bios_from_rom(struct amdgpu_device *adev, dw_ptr = (u32 *)bios; length_dw = ALIGN(length_bytes, 4) / 4; + switch (adev->asic_type) { + case CHIP_VEGA20: + case CHIP_ARCTURUS: + rom_index_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX_VG20); + rom_data_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA_VG20); + break; + default: + rom_index_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX); + rom_data_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA); + break; + } + /* set rom index to 0 */ - WREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX), 0); + WREG32(rom_index_offset, 0); /* read out the rom data */ for (i = 0; i < length_dw; i++) - dw_ptr[i] = RREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA)); + dw_ptr[i] = RREG32(rom_data_offset); return true; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 16218a202b59..28a6c7b2ef4b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -379,6 +379,7 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, aconnector->dc_sink); dc_sink_release(aconnector->dc_sink); aconnector->dc_sink = NULL; + aconnector->dc_link->cur_link_settings.lane_count = 0; } drm_connector_unregister(connector); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index a02c10e23e0d..d163388c99a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -840,8 +840,8 @@ static void hubbub1_det_request_size( hubbub1_get_blk256_size(&blk256_width, &blk256_height, bpe); - swath_bytes_horz_wc = height * blk256_height * bpe; - swath_bytes_vert_wc = width * blk256_width * bpe; + swath_bytes_horz_wc = width * blk256_height * bpe; + swath_bytes_vert_wc = height * blk256_width * bpe; *req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ? false : /* full 256B request */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 3b7769a3e67e..c13dce760098 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -269,6 +269,117 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = { .use_urgent_burst_bw = 0 }; +struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = { + .clock_limits = { + { + .state = 0, + .dcfclk_mhz = 560.0, + .fabricclk_mhz = 560.0, + .dispclk_mhz = 513.0, + .dppclk_mhz = 513.0, + .phyclk_mhz = 540.0, + .socclk_mhz = 560.0, + .dscclk_mhz = 171.0, + .dram_speed_mts = 8960.0, + }, + { + .state = 1, + .dcfclk_mhz = 694.0, + .fabricclk_mhz = 694.0, + .dispclk_mhz = 642.0, + .dppclk_mhz = 642.0, + .phyclk_mhz = 600.0, + .socclk_mhz = 694.0, + .dscclk_mhz = 214.0, + .dram_speed_mts = 11104.0, + }, + { + .state = 2, + .dcfclk_mhz = 875.0, + .fabricclk_mhz = 875.0, + .dispclk_mhz = 734.0, + .dppclk_mhz = 734.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 875.0, + .dscclk_mhz = 245.0, + .dram_speed_mts = 14000.0, + }, + { + .state = 3, + .dcfclk_mhz = 1000.0, + .fabricclk_mhz = 1000.0, + .dispclk_mhz = 1100.0, + .dppclk_mhz = 1100.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1000.0, + .dscclk_mhz = 367.0, + .dram_speed_mts = 16000.0, + }, + { + .state = 4, + .dcfclk_mhz = 1200.0, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 1284.0, + .dppclk_mhz = 1284.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1200.0, + .dscclk_mhz = 428.0, + .dram_speed_mts = 16000.0, + }, + /*Extra state, no dispclk ramping*/ + { + .state = 5, + .dcfclk_mhz = 1200.0, + .fabricclk_mhz = 1200.0, + .dispclk_mhz = 1284.0, + .dppclk_mhz = 1284.0, + .phyclk_mhz = 810.0, + .socclk_mhz = 1200.0, + .dscclk_mhz = 428.0, + .dram_speed_mts = 16000.0, + }, + }, + .num_states = 5, + .sr_exit_time_us = 8.6, + .sr_enter_plus_exit_time_us = 10.9, + .urgent_latency_us = 4.0, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, + .max_avg_sdp_bw_use_normal_percent = 40.0, + .max_avg_dram_bw_use_normal_percent = 40.0, + .writeback_latency_us = 12.0, + .ideal_dram_bw_after_urgent_percent = 40.0, + .max_request_size_bytes = 256, + .dram_channel_width_bytes = 2, + .fabric_datapath_to_dcn_data_return_bytes = 64, + .dcn_downspread_percent = 0.5, + .downspread_percent = 0.38, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 131, + .urgent_out_of_order_return_per_channel_bytes = 256, + .channel_interleave_bytes = 256, + .num_banks = 8, + .num_chans = 8, + .vmm_page_size_bytes = 4096, + .dram_clock_change_latency_us = 404.0, + .dummy_pstate_latency_us = 5.0, + .writeback_dram_clock_change_latency_us = 23.0, + .return_bus_width_bytes = 64, + .dispclk_dppclk_vco_speed_mhz = 3850, + .xfc_bus_transport_time_us = 20, + .xfc_xbuf_latency_tolerance_us = 4, + .use_urgent_burst_bw = 0 +}; + struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 }; #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL @@ -3135,6 +3246,9 @@ static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_s static struct _vcs_dpi_soc_bounding_box_st *get_asic_rev_soc_bb( uint32_t hw_internal_rev) { + if (ASICREV_IS_NAVI14_M(hw_internal_rev)) + return &dcn2_0_nv14_soc; + if (ASICREV_IS_NAVI12_P(hw_internal_rev)) return &dcn2_0_nv12_soc; diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index c5257ae3188a..0922d9cd858a 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -988,8 +988,12 @@ static int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu) struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks; int ret = 0; - max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks), + if (!smu->smu_table.max_sustainable_clocks) + max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks), GFP_KERNEL); + else + max_sustainable_clocks = smu->smu_table.max_sustainable_clocks; + smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks; max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 1326f2c734bf..41bf4aaff21c 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -1576,28 +1576,34 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) frame.colorspace = HDMI_COLORSPACE_RGB; /* Set up colorimetry */ - switch (hdmi->hdmi_data.enc_out_encoding) { - case V4L2_YCBCR_ENC_601: - if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) - frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; - else + if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) { + switch (hdmi->hdmi_data.enc_out_encoding) { + case V4L2_YCBCR_ENC_601: + if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601) + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; + else + frame.colorimetry = HDMI_COLORIMETRY_ITU_601; + frame.extended_colorimetry = + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; + break; + case V4L2_YCBCR_ENC_709: + if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; + else + frame.colorimetry = HDMI_COLORIMETRY_ITU_709; + frame.extended_colorimetry = + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; + break; + default: /* Carries no data */ frame.colorimetry = HDMI_COLORIMETRY_ITU_601; + frame.extended_colorimetry = + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; + break; + } + } else { + frame.colorimetry = HDMI_COLORIMETRY_NONE; frame.extended_colorimetry = - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - break; - case V4L2_YCBCR_ENC_709: - if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709) - frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; - else - frame.colorimetry = HDMI_COLORIMETRY_ITU_709; - frame.extended_colorimetry = - HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; - break; - default: /* Carries no data */ - frame.colorimetry = HDMI_COLORIMETRY_ITU_601; - frame.extended_colorimetry = - HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; - break; + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; } frame.scan_mode = HDMI_SCAN_MODE_NONE; diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 12e748b202d6..bf1bdb0aac19 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -114,33 +114,6 @@ drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc) return NULL; } -static struct drm_display_mode * -drm_connector_get_tiled_mode(struct drm_connector *connector) -{ - struct drm_display_mode *mode; - - list_for_each_entry(mode, &connector->modes, head) { - if (mode->hdisplay == connector->tile_h_size && - mode->vdisplay == connector->tile_v_size) - return mode; - } - return NULL; -} - -static struct drm_display_mode * -drm_connector_fallback_non_tiled_mode(struct drm_connector *connector) -{ - struct drm_display_mode *mode; - - list_for_each_entry(mode, &connector->modes, head) { - if (mode->hdisplay == connector->tile_h_size && - mode->vdisplay == connector->tile_v_size) - continue; - return mode; - } - return NULL; -} - static struct drm_display_mode * drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height) { @@ -375,15 +348,8 @@ static bool drm_client_target_preferred(struct drm_connector **connectors, struct drm_connector *connector; u64 conn_configured = 0; int tile_pass = 0; - int num_tiled_conns = 0; int i; - for (i = 0; i < connector_count; i++) { - if (connectors[i]->has_tile && - connectors[i]->status == connector_status_connected) - num_tiled_conns++; - } - retry: for (i = 0; i < connector_count; i++) { connector = connectors[i]; @@ -433,28 +399,6 @@ retry: list_for_each_entry(modes[i], &connector->modes, head) break; } - /* - * In case of tiled mode if all tiles not present fallback to - * first available non tiled mode. - * After all tiles are present, try to find the tiled mode - * for all and if tiled mode not present due to fbcon size - * limitations, use first non tiled mode only for - * tile 0,0 and set to no mode for all other tiles. - */ - if (connector->has_tile) { - if (num_tiled_conns < - connector->num_h_tile * connector->num_v_tile || - (connector->tile_h_loc == 0 && - connector->tile_v_loc == 0 && - !drm_connector_get_tiled_mode(connector))) { - DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", - connector->base.id); - modes[i] = drm_connector_fallback_non_tiled_mode(connector); - } else { - modes[i] = drm_connector_get_tiled_mode(connector); - } - } - DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : "none"); conn_configured |= BIT_ULL(i); @@ -572,7 +516,6 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, bool fallback = true, ret = true; int num_connectors_enabled = 0; int num_connectors_detected = 0; - int num_tiled_conns = 0; struct drm_modeset_acquire_ctx ctx; if (!drm_drv_uses_atomic_modeset(dev)) @@ -590,11 +533,6 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, memcpy(save_enabled, enabled, count); mask = GENMASK(count - 1, 0); conn_configured = 0; - for (i = 0; i < count; i++) { - if (connectors[i]->has_tile && - connectors[i]->status == connector_status_connected) - num_tiled_conns++; - } retry: conn_seq = conn_configured; for (i = 0; i < count; i++) { @@ -694,16 +632,6 @@ retry: connector->name); modes[i] = &connector->state->crtc->mode; } - /* - * In case of tiled modes, if all tiles are not present - * then fallback to a non tiled mode. - */ - if (connector->has_tile && - num_tiled_conns < connector->num_h_tile * connector->num_v_tile) { - DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", - connector->base.id); - modes[i] = drm_connector_fallback_non_tiled_mode(connector); - } crtcs[i] = new_crtc; DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", @@ -952,7 +880,8 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation) * depending on the hardware this may require the framebuffer * to be in a specific tiling format. */ - if ((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180 || + if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 && + (*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) || !plane->rotation_property) return false; diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 37f360e6ad50..8b6dd549f301 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -341,17 +341,27 @@ EXPORT_SYMBOL(drm_dp_dpcd_read_link_status); * @aux: DisplayPort AUX channel * @real_edid_checksum: real edid checksum for the last block * - * Returns true on success + * Returns: + * True on success */ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, u8 real_edid_checksum) { u8 link_edid_read = 0, auto_test_req = 0, test_resp = 0; - drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, &auto_test_req, 1); + if (drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, + &auto_test_req, 1) < 1) { + DRM_ERROR("DPCD failed read at register 0x%x\n", + DP_DEVICE_SERVICE_IRQ_VECTOR); + return false; + } auto_test_req &= DP_AUTOMATED_TEST_REQUEST; - drm_dp_dpcd_read(aux, DP_TEST_REQUEST, &link_edid_read, 1); + if (drm_dp_dpcd_read(aux, DP_TEST_REQUEST, &link_edid_read, 1) < 1) { + DRM_ERROR("DPCD failed read at register 0x%x\n", + DP_TEST_REQUEST); + return false; + } link_edid_read &= DP_TEST_LINK_EDID_READ; if (!auto_test_req || !link_edid_read) { @@ -359,13 +369,27 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, return false; } - drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, &auto_test_req, 1); + if (drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR, + &auto_test_req, 1) < 1) { + DRM_ERROR("DPCD failed write at register 0x%x\n", + DP_DEVICE_SERVICE_IRQ_VECTOR); + return false; + } /* send back checksum for the last edid extension block data */ - drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, &real_edid_checksum, 1); + if (drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM, + &real_edid_checksum, 1) < 1) { + DRM_ERROR("DPCD failed write at register 0x%x\n", + DP_TEST_EDID_CHECKSUM); + return false; + } test_resp |= DP_TEST_EDID_CHECKSUM_WRITE; - drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, &test_resp, 1); + if (drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, &test_resp, 1) < 1) { + DRM_ERROR("DPCD failed write at register 0x%x\n", + DP_TEST_RESPONSE); + return false; + } return true; } diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index e734742486c7..33e0eba00726 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -99,14 +99,6 @@ struct detailed_mode_closure { #define LEVEL_GTF2 2 #define LEVEL_CVT 3 -/*Enum storing luminance types for HDR blocks in EDID*/ -enum luminance_value { - NO_LUMINANCE_DATA = 3, - MAXIMUM_LUMINANCE = 4, - FRAME_AVERAGE_LUMINANCE = 5, - MINIMUM_LUMINANCE = 6 -}; - static const struct edid_quirk { char vendor[4]; int product_id; @@ -2914,20 +2906,16 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, return closure.modes; } -#define VIDEO_CAPABILITY_EXTENDED_DATA_BLOCK 0x0 + #define AUDIO_BLOCK 0x01 #define VIDEO_BLOCK 0x02 #define VENDOR_BLOCK 0x03 #define SPEAKER_BLOCK 0x04 -#define COLORIMETRY_EXTENDED_DATA_BLOCK 0x05 #define HDR_STATIC_METADATA_BLOCK 0x6 #define USE_EXTENDED_TAG 0x07 #define EXT_VIDEO_CAPABILITY_BLOCK 0x00 #define EXT_VIDEO_DATA_BLOCK_420 0x0E #define EXT_VIDEO_CAP_BLOCK_Y420CMDB 0x0F -#define VENDOR_SPECIFIC_VIDEO_DATA_BLOCK 0x01 -#define VSVDB_HDR10_PLUS_IEEE_CODE 0x90848b -#define VSVDB_HDR10_PLUS_APP_VER_MASK 0x3 #define EDID_BASIC_AUDIO (1 << 6) #define EDID_CEA_YCRCB444 (1 << 5) #define EDID_CEA_YCRCB422 (1 << 4) @@ -3961,48 +3949,6 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode) mode->clock = clock; } -static bool cea_db_is_hdmi_colorimetry_data_block(const u8 *db) -{ - if (cea_db_tag(db) != USE_EXTENDED_TAG) - return false; - - if (db[1] != COLORIMETRY_EXTENDED_DATA_BLOCK) - return false; - - if (cea_db_payload_len(db) < 2) - return false; - - return true; -} - -static void -drm_parse_colorimetry_data_block(struct drm_connector *connector, const u8 *db) -{ - struct drm_hdmi_info *info = &connector->display_info.hdmi; - - if (db[2] & DRM_EDID_CLRMETRY_xvYCC_601) - info->colorimetry |= DRM_EDID_CLRMETRY_xvYCC_601; - if (db[2] & DRM_EDID_CLRMETRY_xvYCC_709) - info->colorimetry |= DRM_EDID_CLRMETRY_xvYCC_709; - if (db[2] & DRM_EDID_CLRMETRY_sYCC_601) - info->colorimetry |= DRM_EDID_CLRMETRY_sYCC_601; - if (db[2] & DRM_EDID_CLRMETRY_ADBYCC_601) - info->colorimetry |= DRM_EDID_CLRMETRY_ADBYCC_601; - if (db[2] & DRM_EDID_CLRMETRY_ADB_RGB) - info->colorimetry |= DRM_EDID_CLRMETRY_ADB_RGB; - if (db[2] & DRM_EDID_CLRMETRY_BT2020_CYCC) - info->colorimetry |= DRM_EDID_CLRMETRY_BT2020_CYCC; - if (db[2] & DRM_EDID_CLRMETRY_BT2020_YCC) - info->colorimetry |= DRM_EDID_CLRMETRY_BT2020_YCC; - if (db[2] & DRM_EDID_CLRMETRY_BT2020_RGB) - info->colorimetry |= DRM_EDID_CLRMETRY_BT2020_RGB; - /* Byte 4 Bit 7: DCI-P3 */ - if (db[3] & BIT(7)) - info->colorimetry |= DRM_EDID_CLRMETRY_DCI_P3; - - DRM_DEBUG_KMS("Supported Colorimetry 0x%x\n", info->colorimetry); -} - static bool cea_db_is_hdmi_hdr_metadata_block(const u8 *db) { if (cea_db_tag(db) != USE_EXTENDED_TAG) @@ -4083,232 +4029,6 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db) connector->audio_latency[1]); } -/* - * drm_extract_vcdb_info - Parse the HDMI Video Capability Data Block - * @connector: connector corresponding to the HDMI sink - * @db: start of the CEA vendor specific block - * - * Parses the HDMI VCDB to extract sink info for @connector. - */ -static void -drm_extract_vcdb_info(struct drm_connector *connector, const u8 *db) -{ - /* - * Check if the sink specifies underscan - * support for: - * BIT 5: preferred video format - * BIT 3: IT video format - * BIT 1: CE video format - */ - - connector->pt_scan_info = - (db[2] & (BIT(4) | BIT(5))) >> 4; - connector->it_scan_info = - (db[2] & (BIT(3) | BIT(2))) >> 2; - connector->ce_scan_info = - db[2] & (BIT(1) | BIT(0)); - - DRM_DEBUG_KMS("Scan Info (pt|it|ce): (%d|%d|%d)", - (int) connector->pt_scan_info, - (int) connector->it_scan_info, - (int) connector->ce_scan_info); -} - -static void -drm_parse_vsvdb_hdr_plus(struct drm_connector *connector, const u8 *db) -{ - connector->hdr_plus_app_ver = db[5] & VSVDB_HDR10_PLUS_APP_VER_MASK; -} - -static void -drm_extract_vsvdb_info(struct drm_connector *connector, const u8 *db) -{ - u8 db_len = cea_db_payload_len(db); - u32 ieee_code = 0; - - if (db_len < 5) - return; - - /* Bytes 2-4: IEEE 24-bit code, LSB first */ - ieee_code = db[2] | (db[3] << 8) | (db[4] << 16); - DRM_DEBUG_KMS("found VSVDB with IEEE code 0x%x\n", ieee_code); - if (ieee_code == VSVDB_HDR10_PLUS_IEEE_CODE) - drm_parse_vsvdb_hdr_plus(connector, db); -} - -static bool drm_edid_is_luminance_value_present( -u32 block_length, enum luminance_value value) -{ - return block_length > NO_LUMINANCE_DATA && value <= block_length; -} - -/* - * drm_extract_clrmetry_db - Parse the HDMI colorimetry extended block - * @connector: connector corresponding to the HDMI sink - * @db: start of the HDMI colorimetry extended block - * - * Parses the HDMI colorimetry block to extract sink info for @connector. - */ -static void -drm_extract_clrmetry_db(struct drm_connector *connector, const u8 *db) -{ - - if (!db) { - DRM_ERROR("invalid db\n"); - return; - } - - /* Byte 3 Bit 0: xvYCC_601 */ - if (db[2] & BIT(0)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_xvYCC_601; - /* Byte 3 Bit 1: xvYCC_709 */ - if (db[2] & BIT(1)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_xvYCC_709; - /* Byte 3 Bit 2: sYCC_601 */ - if (db[2] & BIT(2)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_sYCC_601; - /* Byte 3 Bit 3: ADBYCC_601 */ - if (db[2] & BIT(3)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_ADBYCC_601; - /* Byte 3 Bit 4: ADB_RGB */ - if (db[2] & BIT(4)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_ADB_RGB; - /* Byte 3 Bit 5: BT2020_CYCC */ - if (db[2] & BIT(5)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_BT2020_CYCC; - /* Byte 3 Bit 6: BT2020_YCC */ - if (db[2] & BIT(6)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_BT2020_YCC; - /* Byte 3 Bit 7: BT2020_RGB */ - if (db[2] & BIT(7)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_BT2020_RGB; - /* Byte 4 Bit 7: DCI-P3 */ - if (db[3] & BIT(7)) - connector->color_enc_fmt |= DRM_EDID_CLRMETRY_DCI_P3; - - DRM_DEBUG_KMS("colorimetry fmts = 0x%x\n", connector->color_enc_fmt); -} - -/* - * drm_extract_hdr_db - Parse the HDMI HDR extended block - * @connector: connector corresponding to the HDMI sink - * @db: start of the HDMI HDR extended block - * - * Parses the HDMI HDR extended block to extract sink info for @connector. - */ -static void -drm_extract_hdr_db(struct drm_connector *connector, const u8 *db) -{ - - u8 len = 0; - - if (!db) - return; - - len = db[0] & 0x1f; - /* Byte 3: Electro-Optical Transfer Functions */ - connector->hdr_eotf = db[2] & 0x3F; - - /* Byte 4: Static Metadata Descriptor Type 1 */ - connector->hdr_metadata_type_one = (db[3] & BIT(0)); - - /* Byte 5: Desired Content Maximum Luminance */ - if (drm_edid_is_luminance_value_present(len, MAXIMUM_LUMINANCE)) - connector->hdr_max_luminance = - db[MAXIMUM_LUMINANCE]; - - /* Byte 6: Desired Content Max Frame-average Luminance */ - if (drm_edid_is_luminance_value_present(len, FRAME_AVERAGE_LUMINANCE)) - connector->hdr_avg_luminance = - db[FRAME_AVERAGE_LUMINANCE]; - - /* Byte 7: Desired Content Min Luminance */ - if (drm_edid_is_luminance_value_present(len, MINIMUM_LUMINANCE)) - connector->hdr_min_luminance = - db[MINIMUM_LUMINANCE]; - - connector->hdr_supported = true; - - DRM_DEBUG_KMS("HDR electro-optical %d\n", connector->hdr_eotf); - DRM_DEBUG_KMS("metadata desc 1 %d\n", connector->hdr_metadata_type_one); - DRM_DEBUG_KMS("max luminance %d\n", connector->hdr_max_luminance); - DRM_DEBUG_KMS("avg luminance %d\n", connector->hdr_avg_luminance); - DRM_DEBUG_KMS("min luminance %d\n", connector->hdr_min_luminance); -} -/* - * drm_hdmi_extract_extended_blk_info - Parse the HDMI extended tag blocks - * @connector: connector corresponding to the HDMI sink - * @edid: handle to the EDID structure - * Parses the all extended tag blocks extract sink info for @connector. - */ -static void -drm_hdmi_extract_extended_blk_info(struct drm_connector *connector, - const struct edid *edid) -{ - const u8 *cea = drm_find_cea_extension(edid); - const u8 *db = NULL; - - if (cea && cea_revision(cea) >= 3) { - int i, start, end; - - if (cea_db_offsets(cea, &start, &end)) - return; - - for_each_cea_db(cea, i, start, end) { - db = &cea[i]; - - if (cea_db_tag(db) == USE_EXTENDED_TAG) { - DRM_DEBUG_KMS("found extended tag block = %d\n", - db[1]); - switch (db[1]) { - case VIDEO_CAPABILITY_EXTENDED_DATA_BLOCK: - drm_extract_vcdb_info(connector, db); - break; - case VENDOR_SPECIFIC_VIDEO_DATA_BLOCK: - drm_extract_vsvdb_info(connector, db); - break; - case HDR_STATIC_METADATA_BLOCK: - drm_extract_hdr_db(connector, db); - break; - case COLORIMETRY_EXTENDED_DATA_BLOCK: - drm_extract_clrmetry_db(connector, db); - break; - default: - break; - } - } - } - } -} - -static void -parse_hdmi_hf_vsdb(struct drm_connector *connector, const u8 *db) -{ - u8 len = cea_db_payload_len(db); - - if (len < 7) - return; - - if (db[4] != 1) - return; /* invalid version */ - - connector->max_tmds_char = db[5] * 5; - connector->scdc_present = db[6] & (1 << 7); - connector->rr_capable = db[6] & (1 << 6); - connector->flags_3d = db[6] & 0x7; - connector->supports_scramble = connector->scdc_present && - (db[6] & (1 << 3)); - - DRM_DEBUG_KMS( - "HDMI v2: max TMDS char %d, scdc %s, rr %s,3D flags 0x%x, scramble %s\n", - connector->max_tmds_char, - connector->scdc_present ? "available" : "not available", - connector->rr_capable ? "capable" : "not capable", - connector->flags_3d, - connector->supports_scramble ? "supported" : "not supported"); -} - - static void monitor_name(struct detailed_timing *t, void *data) { @@ -4441,9 +4161,6 @@ static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) /* HDMI Vendor-Specific Data Block */ if (cea_db_is_hdmi_vsdb(db)) drm_parse_hdmi_vsdb_audio(connector, db); - /* HDMI Forum Vendor-Specific Data Block */ - else if (cea_db_is_hdmi_forum_vsdb(db)) - parse_hdmi_hf_vsdb(connector, db); break; default: break; @@ -4910,8 +4627,6 @@ static void drm_parse_cea_ext(struct drm_connector *connector, drm_parse_vcdb(connector, db); if (cea_db_is_hdmi_hdr_metadata_block(db)) drm_parse_hdr_metadata_block(connector, db); - if (cea_db_is_hdmi_colorimetry_data_block(db)) - drm_parse_colorimetry_data_block(connector, db); } } @@ -4938,39 +4653,6 @@ drm_reset_display_info(struct drm_connector *connector) info->non_desktop = 0; } -static void -drm_hdmi_extract_vsdbs_info(struct drm_connector *connector, - const struct edid *edid) -{ - const u8 *cea = drm_find_cea_extension(edid); - const u8 *db = NULL; - - if (cea && cea_revision(cea) >= 3) { - int i, start, end; - - if (cea_db_offsets(cea, &start, &end)) - return; - - for_each_cea_db(cea, i, start, end) { - db = &cea[i]; - - if (cea_db_tag(db) == VENDOR_BLOCK) { - /* HDMI Vendor-Specific Data Block */ - if (cea_db_is_hdmi_vsdb(db)) { - drm_parse_hdmi_vsdb_video( - connector, db); - drm_parse_hdmi_vsdb_audio( - connector, db); - } - /* HDMI Forum Vendor-Specific Data Block */ - else if (cea_db_is_hdmi_forum_vsdb(db)) - parse_hdmi_hf_vsdb(connector, db); - } - } - } -} - - u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid) { struct drm_display_info *info = &connector->display_info; @@ -5008,11 +4690,6 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi connector->name, info->bpc); } - /* Extract audio and video latency fields for the sink */ - drm_hdmi_extract_vsdbs_info(connector, edid); - /* Extract info from extended tag blocks */ - drm_hdmi_extract_extended_blk_info(connector, edid); - /* Only defined for 1.4 with digital displays */ if (edid->revision < 4) return quirks; diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index b481cafdde28..825abe38201a 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c @@ -542,10 +542,12 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev, } DRM_DEBUG_LEASE("Creating lease\n"); + /* lessee will take the ownership of leases */ lessee = drm_lease_create(lessor, &leases); if (IS_ERR(lessee)) { ret = PTR_ERR(lessee); + idr_destroy(&leases); goto out_leases; } @@ -580,7 +582,6 @@ out_lessee: out_leases: put_unused_fd(fd); - idr_destroy(&leases); DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret); return ret; diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index ac39835db8e7..bdeca2f547b5 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1672,6 +1672,13 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len, } } + if (!(rotation & DRM_MODE_ROTATE_MASK)) + rotation |= DRM_MODE_ROTATE_0; + + /* Make sure there is exactly one rotation defined */ + if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK)) + return -EINVAL; + mode->rotation_reflection = rotation; return 0; diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 2d5cbfda3ca7..9c262daf5816 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -55,6 +55,7 @@ static const char * const decon_clks_name[] = { struct decon_context { struct device *dev; struct drm_device *drm_dev; + void *dma_priv; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[WINDOWS_NR]; struct exynos_drm_plane_config configs[WINDOWS_NR]; @@ -644,7 +645,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) decon_clear_channels(ctx->crtc); - return exynos_drm_register_dma(drm_dev, dev); + return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv); } static void decon_unbind(struct device *dev, struct device *master, void *data) @@ -654,7 +655,7 @@ static void decon_unbind(struct device *dev, struct device *master, void *data) decon_disable(ctx->crtc); /* detach this sub driver from iommu mapping if supported. */ - exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev); + exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv); } static const struct component_ops decon_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index f0640950bd46..6fd40410dfd2 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -40,6 +40,7 @@ struct decon_context { struct device *dev; struct drm_device *drm_dev; + void *dma_priv; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[WINDOWS_NR]; struct exynos_drm_plane_config configs[WINDOWS_NR]; @@ -127,13 +128,13 @@ static int decon_ctx_initialize(struct decon_context *ctx, decon_clear_channels(ctx->crtc); - return exynos_drm_register_dma(drm_dev, ctx->dev); + return exynos_drm_register_dma(drm_dev, ctx->dev, &ctx->dma_priv); } static void decon_ctx_remove(struct decon_context *ctx) { /* detach this sub driver from iommu mapping if supported. */ - exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev); + exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv); } static u32 decon_calc_clkdiv(struct decon_context *ctx, diff --git a/drivers/gpu/drm/exynos/exynos_drm_dma.c b/drivers/gpu/drm/exynos/exynos_drm_dma.c index 9ebc02768847..619f81435c1b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dma.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dma.c @@ -58,7 +58,7 @@ static inline void clear_dma_max_seg_size(struct device *dev) * mapping. */ static int drm_iommu_attach_device(struct drm_device *drm_dev, - struct device *subdrv_dev) + struct device *subdrv_dev, void **dma_priv) { struct exynos_drm_private *priv = drm_dev->dev_private; int ret; @@ -74,7 +74,14 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev, return ret; if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { - if (to_dma_iommu_mapping(subdrv_dev)) + /* + * Keep the original DMA mapping of the sub-device and + * restore it on Exynos DRM detach, otherwise the DMA + * framework considers it as IOMMU-less during the next + * probe (in case of deferred probe or modular build) + */ + *dma_priv = to_dma_iommu_mapping(subdrv_dev); + if (*dma_priv) arm_iommu_detach_device(subdrv_dev); ret = arm_iommu_attach_device(subdrv_dev, priv->mapping); @@ -98,19 +105,21 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev, * mapping */ static void drm_iommu_detach_device(struct drm_device *drm_dev, - struct device *subdrv_dev) + struct device *subdrv_dev, void **dma_priv) { struct exynos_drm_private *priv = drm_dev->dev_private; - if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) + if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { arm_iommu_detach_device(subdrv_dev); - else if (IS_ENABLED(CONFIG_IOMMU_DMA)) + arm_iommu_attach_device(subdrv_dev, *dma_priv); + } else if (IS_ENABLED(CONFIG_IOMMU_DMA)) iommu_detach_device(priv->mapping, subdrv_dev); clear_dma_max_seg_size(subdrv_dev); } -int exynos_drm_register_dma(struct drm_device *drm, struct device *dev) +int exynos_drm_register_dma(struct drm_device *drm, struct device *dev, + void **dma_priv) { struct exynos_drm_private *priv = drm->dev_private; @@ -137,13 +146,14 @@ int exynos_drm_register_dma(struct drm_device *drm, struct device *dev) priv->mapping = mapping; } - return drm_iommu_attach_device(drm, dev); + return drm_iommu_attach_device(drm, dev, dma_priv); } -void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev) +void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev, + void **dma_priv) { if (IS_ENABLED(CONFIG_EXYNOS_IOMMU)) - drm_iommu_detach_device(drm, dev); + drm_iommu_detach_device(drm, dev, dma_priv); } void exynos_drm_cleanup_dma(struct drm_device *drm) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index d4014ba592fd..735f436c857c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -223,8 +223,10 @@ static inline bool is_drm_iommu_supported(struct drm_device *drm_dev) return priv->mapping ? true : false; } -int exynos_drm_register_dma(struct drm_device *drm, struct device *dev); -void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev); +int exynos_drm_register_dma(struct drm_device *drm, struct device *dev, + void **dma_priv); +void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev, + void **dma_priv); void exynos_drm_cleanup_dma(struct drm_device *drm); #ifdef CONFIG_DRM_EXYNOS_DPI diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 6926cee91b36..8ed94c994800 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1750,8 +1750,9 @@ static int exynos_dsi_probe(struct platform_device *pdev) ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies), dsi->supplies); if (ret) { - dev_info(dev, "failed to get regulators: %d\n", ret); - return -EPROBE_DEFER; + if (ret != -EPROBE_DEFER) + dev_info(dev, "failed to get regulators: %d\n", ret); + return ret; } dsi->clks = devm_kcalloc(dev, @@ -1764,9 +1765,10 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi->clks[i] = devm_clk_get(dev, clk_names[i]); if (IS_ERR(dsi->clks[i])) { if (strcmp(clk_names[i], "sclk_mipi") == 0) { - strcpy(clk_names[i], OLD_SCLK_MIPI_CLK_NAME); - i--; - continue; + dsi->clks[i] = devm_clk_get(dev, + OLD_SCLK_MIPI_CLK_NAME); + if (!IS_ERR(dsi->clks[i])) + continue; } dev_info(dev, "failed to get the clock: %s\n", diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index 8ea2e1d77802..29ab8be8604c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -97,6 +97,7 @@ struct fimc_scaler { struct fimc_context { struct exynos_drm_ipp ipp; struct drm_device *drm_dev; + void *dma_priv; struct device *dev; struct exynos_drm_ipp_task *task; struct exynos_drm_ipp_formats *formats; @@ -1133,7 +1134,7 @@ static int fimc_bind(struct device *dev, struct device *master, void *data) ctx->drm_dev = drm_dev; ipp->drm_dev = drm_dev; - exynos_drm_register_dma(drm_dev, dev); + exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv); exynos_drm_ipp_register(dev, ipp, &ipp_funcs, DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE | @@ -1153,7 +1154,7 @@ static void fimc_unbind(struct device *dev, struct device *master, struct exynos_drm_ipp *ipp = &ctx->ipp; exynos_drm_ipp_unregister(dev, ipp); - exynos_drm_unregister_dma(drm_dev, dev); + exynos_drm_unregister_dma(drm_dev, dev, &ctx->dma_priv); } static const struct component_ops fimc_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 8d0a929104e5..34e6b22173fa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -167,6 +167,7 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = { struct fimd_context { struct device *dev; struct drm_device *drm_dev; + void *dma_priv; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[WINDOWS_NR]; struct exynos_drm_plane_config configs[WINDOWS_NR]; @@ -1090,7 +1091,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) if (is_drm_iommu_supported(drm_dev)) fimd_clear_channels(ctx->crtc); - return exynos_drm_register_dma(drm_dev, dev); + return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv); } static void fimd_unbind(struct device *dev, struct device *master, @@ -1100,7 +1101,7 @@ static void fimd_unbind(struct device *dev, struct device *master, fimd_disable(ctx->crtc); - exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev); + exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv); if (ctx->encoder) exynos_dpi_remove(ctx->encoder); diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 2a3382d43bc9..fcee33a43aca 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -232,6 +232,7 @@ struct g2d_runqueue_node { struct g2d_data { struct device *dev; + void *dma_priv; struct clk *gate_clk; void __iomem *regs; int irq; @@ -1409,7 +1410,7 @@ static int g2d_bind(struct device *dev, struct device *master, void *data) return ret; } - ret = exynos_drm_register_dma(drm_dev, dev); + ret = exynos_drm_register_dma(drm_dev, dev, &g2d->dma_priv); if (ret < 0) { dev_err(dev, "failed to enable iommu.\n"); g2d_fini_cmdlist(g2d); @@ -1434,7 +1435,7 @@ static void g2d_unbind(struct device *dev, struct device *master, void *data) priv->g2d_dev = NULL; cancel_work_sync(&g2d->runqueue_work); - exynos_drm_unregister_dma(g2d->drm_dev, dev); + exynos_drm_unregister_dma(g2d->drm_dev, dev, &g2d->dma_priv); } static const struct component_ops g2d_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 88b6fcaa20be..45e9aee8366a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -97,6 +97,7 @@ struct gsc_scaler { struct gsc_context { struct exynos_drm_ipp ipp; struct drm_device *drm_dev; + void *dma_priv; struct device *dev; struct exynos_drm_ipp_task *task; struct exynos_drm_ipp_formats *formats; @@ -1169,7 +1170,7 @@ static int gsc_bind(struct device *dev, struct device *master, void *data) ctx->drm_dev = drm_dev; ctx->drm_dev = drm_dev; - exynos_drm_register_dma(drm_dev, dev); + exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv); exynos_drm_ipp_register(dev, ipp, &ipp_funcs, DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE | @@ -1189,7 +1190,7 @@ static void gsc_unbind(struct device *dev, struct device *master, struct exynos_drm_ipp *ipp = &ctx->ipp; exynos_drm_ipp_unregister(dev, ipp); - exynos_drm_unregister_dma(drm_dev, dev); + exynos_drm_unregister_dma(drm_dev, dev, &ctx->dma_priv); } static const struct component_ops gsc_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index b98482990d1a..dafa87b82052 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -56,6 +56,7 @@ struct rot_variant { struct rot_context { struct exynos_drm_ipp ipp; struct drm_device *drm_dev; + void *dma_priv; struct device *dev; void __iomem *regs; struct clk *clock; @@ -243,7 +244,7 @@ static int rotator_bind(struct device *dev, struct device *master, void *data) rot->drm_dev = drm_dev; ipp->drm_dev = drm_dev; - exynos_drm_register_dma(drm_dev, dev); + exynos_drm_register_dma(drm_dev, dev, &rot->dma_priv); exynos_drm_ipp_register(dev, ipp, &ipp_funcs, DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE, @@ -261,7 +262,7 @@ static void rotator_unbind(struct device *dev, struct device *master, struct exynos_drm_ipp *ipp = &rot->ipp; exynos_drm_ipp_unregister(dev, ipp); - exynos_drm_unregister_dma(rot->drm_dev, rot->dev); + exynos_drm_unregister_dma(rot->drm_dev, rot->dev, &rot->dma_priv); } static const struct component_ops rotator_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c index 497973e9b2c5..93c43c8d914e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c +++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c @@ -39,6 +39,7 @@ struct scaler_data { struct scaler_context { struct exynos_drm_ipp ipp; struct drm_device *drm_dev; + void *dma_priv; struct device *dev; void __iomem *regs; struct clk *clock[SCALER_MAX_CLK]; @@ -450,7 +451,7 @@ static int scaler_bind(struct device *dev, struct device *master, void *data) scaler->drm_dev = drm_dev; ipp->drm_dev = drm_dev; - exynos_drm_register_dma(drm_dev, dev); + exynos_drm_register_dma(drm_dev, dev, &scaler->dma_priv); exynos_drm_ipp_register(dev, ipp, &ipp_funcs, DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE | @@ -470,7 +471,8 @@ static void scaler_unbind(struct device *dev, struct device *master, struct exynos_drm_ipp *ipp = &scaler->ipp; exynos_drm_ipp_unregister(dev, ipp); - exynos_drm_unregister_dma(scaler->drm_dev, scaler->dev); + exynos_drm_unregister_dma(scaler->drm_dev, scaler->dev, + &scaler->dma_priv); } static const struct component_ops scaler_component_ops = { diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 09aa73c0f2ad..0073a2b3b80a 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1802,18 +1802,10 @@ static int hdmi_resources_init(struct hdmi_context *hdata) hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en"); - if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV) { + if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV) if (IS_ERR(hdata->reg_hdmi_en)) return PTR_ERR(hdata->reg_hdmi_en); - ret = regulator_enable(hdata->reg_hdmi_en); - if (ret) { - DRM_DEV_ERROR(dev, - "failed to enable hdmi-en regulator\n"); - return ret; - } - } - return hdmi_bridge_init(hdata); } @@ -2020,6 +2012,15 @@ static int hdmi_probe(struct platform_device *pdev) } } + if (!IS_ERR(hdata->reg_hdmi_en)) { + ret = regulator_enable(hdata->reg_hdmi_en); + if (ret) { + DRM_DEV_ERROR(dev, + "failed to enable hdmi-en regulator\n"); + goto err_hdmiphy; + } + } + pm_runtime_enable(dev); audio_infoframe = &hdata->audio.infoframe; @@ -2044,7 +2045,8 @@ err_unregister_audio: err_rpm_disable: pm_runtime_disable(dev); - + if (!IS_ERR(hdata->reg_hdmi_en)) + regulator_disable(hdata->reg_hdmi_en); err_hdmiphy: if (hdata->hdmiphy_port) put_device(&hdata->hdmiphy_port->dev); diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 7b24338fad3c..22f494145411 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -94,6 +94,7 @@ struct mixer_context { struct platform_device *pdev; struct device *dev; struct drm_device *drm_dev; + void *dma_priv; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR]; unsigned long flags; @@ -894,12 +895,14 @@ static int mixer_initialize(struct mixer_context *mixer_ctx, } } - return exynos_drm_register_dma(drm_dev, mixer_ctx->dev); + return exynos_drm_register_dma(drm_dev, mixer_ctx->dev, + &mixer_ctx->dma_priv); } static void mixer_ctx_remove(struct mixer_context *mixer_ctx) { - exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev); + exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev, + &mixer_ctx->dma_priv); } static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h index ab7fe962d211..6d7f2e8a0479 100755 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h @@ -83,7 +83,6 @@ #define VSIZE_OFST 20 #define LDI_INT_EN 0x741C #define FRAME_END_INT_EN_OFST 1 -#define UNDERFLOW_INT_EN_OFST 2 #define LDI_CTRL 0x7420 #define BPP_OFST 3 #define DATA_GATE_EN BIT(2) diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 73cd28a6ea07..86000127d4ee 100755 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -46,7 +46,6 @@ struct ade_hw_ctx { struct clk *media_noc_clk; struct clk *ade_pix_clk; struct reset_control *reset; - struct work_struct display_reset_wq; bool power_on; int irq; @@ -136,7 +135,6 @@ static void ade_init(struct ade_hw_ctx *ctx) */ ade_update_bits(base + ADE_CTRL, FRM_END_START_OFST, FRM_END_START_MASK, REG_EFFECTIVE_IN_ADEEN_FRMEND); - ade_update_bits(base + LDI_INT_EN, UNDERFLOW_INT_EN_OFST, MASK(1), 1); } static bool ade_crtc_mode_fixup(struct drm_crtc *crtc, @@ -304,17 +302,6 @@ static void ade_crtc_disable_vblank(struct drm_crtc *crtc) MASK(1), 0); } -static void drm_underflow_wq(struct work_struct *work) -{ - struct ade_hw_ctx *ctx = container_of(work, struct ade_hw_ctx, - display_reset_wq); - struct drm_device *drm_dev = ctx->crtc->dev; - struct drm_atomic_state *state; - - state = drm_atomic_helper_suspend(drm_dev); - drm_atomic_helper_resume(drm_dev, state); -} - static irqreturn_t ade_irq_handler(int irq, void *data) { struct ade_hw_ctx *ctx = data; @@ -331,12 +318,6 @@ static irqreturn_t ade_irq_handler(int irq, void *data) MASK(1), 1); drm_crtc_handle_vblank(crtc); } - if (status & BIT(UNDERFLOW_INT_EN_OFST)) { - ade_update_bits(base + LDI_INT_CLR, UNDERFLOW_INT_EN_OFST, - MASK(1), 1); - DRM_ERROR("LDI underflow!"); - schedule_work(&ctx->display_reset_wq); - } return IRQ_HANDLED; } @@ -919,7 +900,6 @@ static void *ade_hw_ctx_alloc(struct platform_device *pdev, if (ret) return ERR_PTR(-EIO); - INIT_WORK(&ctx->display_reset_wq, drm_underflow_wq); ctx->crtc = crtc; return ctx; diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index c002f234ff31..2422af6a99a0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -4205,13 +4205,19 @@ static void icl_dbuf_disable(struct drm_i915_private *dev_priv) static void icl_mbus_init(struct drm_i915_private *dev_priv) { - u32 val; + u32 mask, val; - val = MBUS_ABOX_BT_CREDIT_POOL1(16) | - MBUS_ABOX_BT_CREDIT_POOL2(16) | - MBUS_ABOX_B_CREDIT(1) | - MBUS_ABOX_BW_CREDIT(1); + mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK | + MBUS_ABOX_BT_CREDIT_POOL2_MASK | + MBUS_ABOX_B_CREDIT_MASK | + MBUS_ABOX_BW_CREDIT_MASK; + val = I915_READ(MBUS_ABOX_CTL); + val &= ~mask; + val |= MBUS_ABOX_BT_CREDIT_POOL1(16) | + MBUS_ABOX_BT_CREDIT_POOL2(16) | + MBUS_ABOX_B_CREDIT(1) | + MBUS_ABOX_BW_CREDIT(1); I915_WRITE(MBUS_ABOX_CTL, val); } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index e635e1e5f4d3..bd4e41380777 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -439,7 +439,8 @@ eb_validate_vma(struct i915_execbuffer *eb, if (unlikely(entry->flags & eb->invalid_flags)) return -EINVAL; - if (unlikely(entry->alignment && !is_power_of_2(entry->alignment))) + if (unlikely(entry->alignment && + !is_power_of_2_u64(entry->alignment))) return -EINVAL; /* diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 1d27babff0ce..dc9d3a5ec4a6 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -375,7 +375,7 @@ static bool assert_mmap_offset(struct drm_i915_private *i915, obj = i915_gem_object_create_internal(i915, size); if (IS_ERR(obj)) - return PTR_ERR(obj); + return false; err = create_mmap_offset(obj); i915_gem_object_put(obj); diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index e1c313da6c00..a62bdf9be682 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -457,7 +457,8 @@ void intel_vgpu_emulate_hotplug(struct intel_vgpu *vgpu, bool connected) struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; /* TODO: add more platforms support */ - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) || + IS_COFFEELAKE(dev_priv)) { if (connected) { vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDID_DETECTED; diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index b232965b45b5..32e57635709a 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -272,10 +272,17 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) { struct intel_gvt *gvt = vgpu->gvt; - mutex_lock(&vgpu->vgpu_lock); - WARN(vgpu->active, "vGPU is still active!\n"); + /* + * remove idr first so later clean can judge if need to stop + * service if no active vgpu. + */ + mutex_lock(&gvt->lock); + idr_remove(&gvt->vgpu_idr, vgpu->id); + mutex_unlock(&gvt->lock); + + mutex_lock(&vgpu->vgpu_lock); intel_gvt_debugfs_remove_vgpu(vgpu); intel_vgpu_clean_sched_policy(vgpu); intel_vgpu_clean_submission(vgpu); @@ -290,7 +297,6 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) mutex_unlock(&vgpu->vgpu_lock); mutex_lock(&gvt->lock); - idr_remove(&gvt->vgpu_idr, vgpu->id); if (idr_is_empty(&gvt->vgpu_idr)) intel_gvt_clean_irq(gvt); intel_gvt_update_vgpu_types(gvt); diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 1c5506822dc7..0d39038898d4 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -560,19 +560,31 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) return NOTIFY_DONE; } +static void irq_semaphore_cb(struct irq_work *wrk) +{ + struct i915_request *rq = + container_of(wrk, typeof(*rq), semaphore_work); + + i915_schedule_bump_priority(rq, I915_PRIORITY_NOSEMAPHORE); + i915_request_put(rq); +} + static int __i915_sw_fence_call semaphore_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) { - struct i915_request *request = - container_of(fence, typeof(*request), semaphore); + struct i915_request *rq = container_of(fence, typeof(*rq), semaphore); switch (state) { case FENCE_COMPLETE: - i915_schedule_bump_priority(request, I915_PRIORITY_NOSEMAPHORE); + if (!(READ_ONCE(rq->sched.attr.priority) & I915_PRIORITY_NOSEMAPHORE)) { + i915_request_get(rq); + init_irq_work(&rq->semaphore_work, irq_semaphore_cb); + irq_work_queue(&rq->semaphore_work); + } break; case FENCE_FREE: - i915_request_put(request); + i915_request_put(rq); break; } @@ -1215,9 +1227,9 @@ void __i915_request_queue(struct i915_request *rq, * decide whether to preempt the entire chain so that it is ready to * run at the earliest possible convenience. */ - i915_sw_fence_commit(&rq->semaphore); if (attr && rq->engine->schedule) rq->engine->schedule(rq, attr); + i915_sw_fence_commit(&rq->semaphore); i915_sw_fence_commit(&rq->submit); } diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index e4dd013761e8..3a3e7bbf19ff 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -26,6 +26,7 @@ #define I915_REQUEST_H #include +#include #include #include "gt/intel_context_types.h" @@ -147,6 +148,7 @@ struct i915_request { }; struct list_head execute_cb; struct i915_sw_fence semaphore; + struct irq_work semaphore_work; /* * A list of everyone we wait upon, and everyone who waits upon us. diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 562f756da421..5b1622a40baa 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -233,6 +233,11 @@ static inline u64 ptr_to_u64(const void *ptr) __idx; \ }) +static inline bool is_power_of_2_u64(u64 n) +{ + return (n != 0 && ((n & (n - 1)) == 0)); +} + static inline void __list_del_many(struct list_head *head, struct list_head *first) { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index e6c049f4f08b..f9455f2724d2 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -496,10 +496,18 @@ static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = { static int mtk_drm_crtc_init(struct drm_device *drm, struct mtk_drm_crtc *mtk_crtc, - struct drm_plane *primary, - struct drm_plane *cursor, unsigned int pipe) + unsigned int pipe) { - int ret; + struct drm_plane *primary = NULL; + struct drm_plane *cursor = NULL; + int i, ret; + + for (i = 0; i < mtk_crtc->layer_nr; i++) { + if (mtk_crtc->planes[i].type == DRM_PLANE_TYPE_PRIMARY) + primary = &mtk_crtc->planes[i]; + else if (mtk_crtc->planes[i].type == DRM_PLANE_TYPE_CURSOR) + cursor = &mtk_crtc->planes[i]; + } ret = drm_crtc_init_with_planes(drm, &mtk_crtc->base, primary, cursor, &mtk_crtc_funcs, NULL); @@ -608,9 +616,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, return ret; } - ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, &mtk_crtc->planes[0], - mtk_crtc->layer_nr > 1 ? &mtk_crtc->planes[1] : - NULL, pipe); + ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, pipe); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c index eb0b4b7dc7cc..03c6d6157e4d 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c @@ -1112,8 +1112,8 @@ static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc) ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion, msecs_to_jiffies(50)); if (ret == 0) - dev_warn(dev->dev, "pp done time out, lm=%d\n", - mdp5_cstate->pipeline.mixer->lm); + dev_warn_ratelimited(dev->dev, "pp done time out, lm=%d\n", + mdp5_cstate->pipeline.mixer->lm); } static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 271aa7bbca92..73127948f54d 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -336,7 +336,7 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector) return num; } -static int dsi_mgr_connector_mode_valid(struct drm_connector *connector, +static enum drm_mode_status dsi_mgr_connector_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { int id = dsi_mgr_connector_get_id(connector); @@ -479,6 +479,7 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); struct mipi_dsi_host *host = msm_dsi->host; struct drm_panel *panel = msm_dsi->panel; + struct msm_dsi_pll *src_pll; bool is_dual_dsi = IS_DUAL_DSI(); int ret; @@ -519,6 +520,10 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) id, ret); } + /* Save PLL status if it is a clock source */ + src_pll = msm_dsi_phy_get_pll(msm_dsi->phy); + msm_dsi_pll_save_state(src_pll); + ret = msm_dsi_host_power_off(host); if (ret) pr_err("%s: host %d power off failed,%d\n", __func__, id, ret); diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 3522863a4984..21519229fe73 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -724,10 +724,6 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy) if (!phy || !phy->cfg->ops.disable) return; - /* Save PLL status if it is a clock source */ - if (phy->usecase != MSM_DSI_PHY_SLAVE) - msm_dsi_pll_save_state(phy->pll); - phy->cfg->ops.disable(phy); dsi_phy_regulator_disable(phy); diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c index 8f6100db90ed..aa9385d5bfff 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c @@ -411,6 +411,12 @@ static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw) if (pll_10nm->slave) dsi_pll_enable_pll_bias(pll_10nm->slave); + rc = dsi_pll_10nm_vco_set_rate(hw,pll_10nm->vco_current_rate, 0); + if (rc) { + pr_err("vco_set_rate failed, rc=%d\n", rc); + return rc; + } + /* Start PLL */ pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL, 0x01); diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 3107b0738e40..5d75f8cf6477 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -601,33 +601,27 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data) source_id = (fault_status >> 16); /* Page fault only */ - if ((status & mask) == BIT(i)) { - WARN_ON(exception_type < 0xC1 || exception_type > 0xC4); - + ret = -1; + if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0) ret = panfrost_mmu_map_fault_addr(pfdev, i, addr); - if (!ret) { - mmu_write(pfdev, MMU_INT_CLEAR, BIT(i)); - status &= ~mask; - continue; - } - } - /* terminal fault, print info about the fault */ - dev_err(pfdev->dev, - "Unhandled Page fault in AS%d at VA 0x%016llX\n" - "Reason: %s\n" - "raw fault status: 0x%X\n" - "decoded fault status: %s\n" - "exception type 0x%X: %s\n" - "access type 0x%X: %s\n" - "source id 0x%X\n", - i, addr, - "TODO", - fault_status, - (fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"), - exception_type, panfrost_exception_name(pfdev, exception_type), - access_type, access_type_name(pfdev, fault_status), - source_id); + if (ret) + /* terminal fault, print info about the fault */ + dev_err(pfdev->dev, + "Unhandled Page fault in AS%d at VA 0x%016llX\n" + "Reason: %s\n" + "raw fault status: 0x%X\n" + "decoded fault status: %s\n" + "exception type 0x%X: %s\n" + "access type 0x%X: %s\n" + "source id 0x%X\n", + i, addr, + "TODO", + fault_status, + (fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"), + exception_type, panfrost_exception_name(pfdev, exception_type), + access_type, access_type_name(pfdev, fault_status), + source_id); mmu_write(pfdev, MMU_INT_CLEAR, mask); diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h index 6d61a0eb5d64..84e6bc050bf2 100644 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h @@ -53,6 +53,7 @@ cmdline_test(drm_cmdline_test_rotate_0) cmdline_test(drm_cmdline_test_rotate_90) cmdline_test(drm_cmdline_test_rotate_180) cmdline_test(drm_cmdline_test_rotate_270) +cmdline_test(drm_cmdline_test_rotate_multiple) cmdline_test(drm_cmdline_test_rotate_invalid_val) cmdline_test(drm_cmdline_test_rotate_truncated) cmdline_test(drm_cmdline_test_hmirror) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c index 013de9d27c35..035f86c5d648 100644 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c @@ -856,6 +856,17 @@ static int drm_cmdline_test_rotate_270(void *ignored) return 0; } +static int drm_cmdline_test_rotate_multiple(void *ignored) +{ + struct drm_cmdline_mode mode = { }; + + FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=0,rotate=90", + &no_connector, + &mode)); + + return 0; +} + static int drm_cmdline_test_rotate_invalid_val(void *ignored) { struct drm_cmdline_mode mode = { }; @@ -888,7 +899,7 @@ static int drm_cmdline_test_hmirror(void *ignored) FAIL_ON(!mode.specified); FAIL_ON(mode.xres != 720); FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != DRM_MODE_REFLECT_X); + FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X)); FAIL_ON(mode.refresh_specified); @@ -913,7 +924,7 @@ static int drm_cmdline_test_vmirror(void *ignored) FAIL_ON(!mode.specified); FAIL_ON(mode.xres != 720); FAIL_ON(mode.yres != 480); - FAIL_ON(mode.rotation_reflection != DRM_MODE_REFLECT_Y); + FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y)); FAIL_ON(mode.refresh_specified); diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index 8b803eb903b8..18b4881f4481 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -106,48 +106,128 @@ static const struct de2_fmt_info de2_formats[] = { .rgb = true, .csc = SUN8I_CSC_MODE_OFF, }, + { + /* for DE2 VI layer which ignores alpha */ + .drm_fmt = DRM_FORMAT_XRGB4444, + .de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, { .drm_fmt = DRM_FORMAT_ABGR4444, .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444, .rgb = true, .csc = SUN8I_CSC_MODE_OFF, }, + { + /* for DE2 VI layer which ignores alpha */ + .drm_fmt = DRM_FORMAT_XBGR4444, + .de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, { .drm_fmt = DRM_FORMAT_RGBA4444, .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444, .rgb = true, .csc = SUN8I_CSC_MODE_OFF, }, + { + /* for DE2 VI layer which ignores alpha */ + .drm_fmt = DRM_FORMAT_RGBX4444, + .de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, { .drm_fmt = DRM_FORMAT_BGRA4444, .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444, .rgb = true, .csc = SUN8I_CSC_MODE_OFF, }, + { + /* for DE2 VI layer which ignores alpha */ + .drm_fmt = DRM_FORMAT_BGRX4444, + .de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, { .drm_fmt = DRM_FORMAT_ARGB1555, .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555, .rgb = true, .csc = SUN8I_CSC_MODE_OFF, }, + { + /* for DE2 VI layer which ignores alpha */ + .drm_fmt = DRM_FORMAT_XRGB1555, + .de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, { .drm_fmt = DRM_FORMAT_ABGR1555, .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555, .rgb = true, .csc = SUN8I_CSC_MODE_OFF, }, + { + /* for DE2 VI layer which ignores alpha */ + .drm_fmt = DRM_FORMAT_XBGR1555, + .de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, { .drm_fmt = DRM_FORMAT_RGBA5551, .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551, .rgb = true, .csc = SUN8I_CSC_MODE_OFF, }, + { + /* for DE2 VI layer which ignores alpha */ + .drm_fmt = DRM_FORMAT_RGBX5551, + .de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, { .drm_fmt = DRM_FORMAT_BGRA5551, .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551, .rgb = true, .csc = SUN8I_CSC_MODE_OFF, }, + { + /* for DE2 VI layer which ignores alpha */ + .drm_fmt = DRM_FORMAT_BGRX5551, + .de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { + .drm_fmt = DRM_FORMAT_ARGB2101010, + .de2_fmt = SUN8I_MIXER_FBFMT_ARGB2101010, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { + .drm_fmt = DRM_FORMAT_ABGR2101010, + .de2_fmt = SUN8I_MIXER_FBFMT_ABGR2101010, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { + .drm_fmt = DRM_FORMAT_RGBA1010102, + .de2_fmt = SUN8I_MIXER_FBFMT_RGBA1010102, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, + { + .drm_fmt = DRM_FORMAT_BGRA1010102, + .de2_fmt = SUN8I_MIXER_FBFMT_BGRA1010102, + .rgb = true, + .csc = SUN8I_CSC_MODE_OFF, + }, { .drm_fmt = DRM_FORMAT_UYVY, .de2_fmt = SUN8I_MIXER_FBFMT_UYVY, @@ -196,12 +276,6 @@ static const struct de2_fmt_info de2_formats[] = { .rgb = false, .csc = SUN8I_CSC_MODE_YUV2RGB, }, - { - .drm_fmt = DRM_FORMAT_YUV444, - .de2_fmt = SUN8I_MIXER_FBFMT_RGB888, - .rgb = true, - .csc = SUN8I_CSC_MODE_YUV2RGB, - }, { .drm_fmt = DRM_FORMAT_YUV422, .de2_fmt = SUN8I_MIXER_FBFMT_YUV422, @@ -220,12 +294,6 @@ static const struct de2_fmt_info de2_formats[] = { .rgb = false, .csc = SUN8I_CSC_MODE_YUV2RGB, }, - { - .drm_fmt = DRM_FORMAT_YVU444, - .de2_fmt = SUN8I_MIXER_FBFMT_RGB888, - .rgb = true, - .csc = SUN8I_CSC_MODE_YVU2RGB, - }, { .drm_fmt = DRM_FORMAT_YVU422, .de2_fmt = SUN8I_MIXER_FBFMT_YUV422, @@ -244,6 +312,18 @@ static const struct de2_fmt_info de2_formats[] = { .rgb = false, .csc = SUN8I_CSC_MODE_YVU2RGB, }, + { + .drm_fmt = DRM_FORMAT_P010, + .de2_fmt = SUN8I_MIXER_FBFMT_P010_YUV, + .rgb = false, + .csc = SUN8I_CSC_MODE_YUV2RGB, + }, + { + .drm_fmt = DRM_FORMAT_P210, + .de2_fmt = SUN8I_MIXER_FBFMT_P210_YUV, + .rgb = false, + .csc = SUN8I_CSC_MODE_YUV2RGB, + }, }; const struct de2_fmt_info *sun8i_mixer_format_info(u32 format) diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h index c6cc94057faf..345b28b0a80a 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.h +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h @@ -93,6 +93,10 @@ #define SUN8I_MIXER_FBFMT_ABGR1555 17 #define SUN8I_MIXER_FBFMT_RGBA5551 18 #define SUN8I_MIXER_FBFMT_BGRA5551 19 +#define SUN8I_MIXER_FBFMT_ARGB2101010 20 +#define SUN8I_MIXER_FBFMT_ABGR2101010 21 +#define SUN8I_MIXER_FBFMT_RGBA1010102 22 +#define SUN8I_MIXER_FBFMT_BGRA1010102 23 #define SUN8I_MIXER_FBFMT_YUYV 0 #define SUN8I_MIXER_FBFMT_UYVY 1 @@ -109,6 +113,13 @@ /* format 12 is semi-planar YUV411 UVUV */ /* format 13 is semi-planar YUV411 VUVU */ #define SUN8I_MIXER_FBFMT_YUV411 14 +/* format 15 doesn't exist */ +/* format 16 is P010 YVU */ +#define SUN8I_MIXER_FBFMT_P010_YUV 17 +/* format 18 is P210 YVU */ +#define SUN8I_MIXER_FBFMT_P210_YUV 19 +/* format 20 is packed YVU444 10-bit */ +/* format 21 is packed YUV444 10-bit */ /* * Sub-engines listed bellow are unused for now. The EN registers are here only diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 42d445d23773..b8398ca18b0f 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -398,26 +398,26 @@ static const struct drm_plane_funcs sun8i_vi_layer_funcs = { }; /* - * While all RGB formats are supported, VI planes don't support - * alpha blending, so there is no point having formats with alpha - * channel if their opaque analog exist. + * While DE2 VI layer supports same RGB formats as UI layer, alpha + * channel is ignored. This structure lists all unique variants + * where alpha channel is replaced with "don't care" (X) channel. */ static const u32 sun8i_vi_layer_formats[] = { - DRM_FORMAT_ABGR1555, - DRM_FORMAT_ABGR4444, - DRM_FORMAT_ARGB1555, - DRM_FORMAT_ARGB4444, DRM_FORMAT_BGR565, DRM_FORMAT_BGR888, - DRM_FORMAT_BGRA5551, - DRM_FORMAT_BGRA4444, + DRM_FORMAT_BGRX4444, + DRM_FORMAT_BGRX5551, DRM_FORMAT_BGRX8888, DRM_FORMAT_RGB565, DRM_FORMAT_RGB888, - DRM_FORMAT_RGBA4444, - DRM_FORMAT_RGBA5551, + DRM_FORMAT_RGBX4444, + DRM_FORMAT_RGBX5551, DRM_FORMAT_RGBX8888, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_XBGR4444, DRM_FORMAT_XBGR8888, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XRGB4444, DRM_FORMAT_XRGB8888, DRM_FORMAT_NV16, @@ -431,11 +431,53 @@ static const u32 sun8i_vi_layer_formats[] = { DRM_FORMAT_YUV411, DRM_FORMAT_YUV420, DRM_FORMAT_YUV422, - DRM_FORMAT_YUV444, DRM_FORMAT_YVU411, DRM_FORMAT_YVU420, DRM_FORMAT_YVU422, - DRM_FORMAT_YVU444, +}; + +static const u32 sun8i_vi_layer_de3_formats[] = { + DRM_FORMAT_ABGR1555, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_ABGR4444, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_BGR565, + DRM_FORMAT_BGR888, + DRM_FORMAT_BGRA1010102, + DRM_FORMAT_BGRA5551, + DRM_FORMAT_BGRA4444, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGBA1010102, + DRM_FORMAT_RGBA4444, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_XRGB8888, + + DRM_FORMAT_NV16, + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV61, + DRM_FORMAT_P010, + DRM_FORMAT_P210, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_YUV411, + DRM_FORMAT_YUV420, + DRM_FORMAT_YUV422, + DRM_FORMAT_YVU411, + DRM_FORMAT_YVU420, + DRM_FORMAT_YVU422, }; struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, @@ -443,19 +485,27 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, int index) { u32 supported_encodings, supported_ranges; + unsigned int plane_cnt, format_count; struct sun8i_vi_layer *layer; - unsigned int plane_cnt; + const u32 *formats; int ret; layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL); if (!layer) return ERR_PTR(-ENOMEM); + if (mixer->cfg->is_de3) { + formats = sun8i_vi_layer_de3_formats; + format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats); + } else { + formats = sun8i_vi_layer_formats; + format_count = ARRAY_SIZE(sun8i_vi_layer_formats); + } + /* possible crtcs are set later */ ret = drm_universal_plane_init(drm, &layer->plane, 0, &sun8i_vi_layer_funcs, - sun8i_vi_layer_formats, - ARRAY_SIZE(sun8i_vi_layer_formats), + formats, format_count, NULL, DRM_PLANE_TYPE_OVERLAY, NULL); if (ret) { dev_err(drm->dev, "Couldn't initialize layer\n"); diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 09b526518f5a..8de93ccacaac 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -23,38 +23,44 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include + #include #include "virtgpu_drv.h" +static int virtio_gpu_virglrenderer_workaround = 1; +module_param_named(virglhack, virtio_gpu_virglrenderer_workaround, int, 0400); + static int virtio_gpu_resource_id_get(struct virtio_gpu_device *vgdev, uint32_t *resid) { -#if 0 - int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL); - - if (handle < 0) - return handle; -#else - static int handle; - - /* - * FIXME: dirty hack to avoid re-using IDs, virglrenderer - * can't deal with that. Needs fixing in virglrenderer, also - * should figure a better way to handle that in the guest. - */ - handle++; -#endif - - *resid = handle + 1; + if (virtio_gpu_virglrenderer_workaround) { + /* + * Hack to avoid re-using resource IDs. + * + * virglrenderer versions up to (and including) 0.7.0 + * can't deal with that. virglrenderer commit + * "f91a9dd35715 Fix unlinking resources from hash + * table." (Feb 2019) fixes the bug. + */ + static atomic_t seqno = ATOMIC_INIT(0); + int handle = atomic_inc_return(&seqno); + *resid = handle + 1; + } else { + int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL); + if (handle < 0) + return handle; + *resid = handle + 1; + } return 0; } static void virtio_gpu_resource_id_put(struct virtio_gpu_device *vgdev, uint32_t id) { -#if 0 - ida_free(&vgdev->resource_ida, id - 1); -#endif + if (!virtio_gpu_virglrenderer_workaround) { + ida_free(&vgdev->resource_ida, id - 1); + } } static void virtio_gpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 6ac8becc2372..d732d1d10caf 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -340,7 +340,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi, unsigned long **bit, int *max) { if (usage->hid == (HID_UP_CUSTOM | 0x0003) || - usage->hid == (HID_UP_MSVENDOR | 0x0003)) { + usage->hid == (HID_UP_MSVENDOR | 0x0003) || + usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) { /* The fn key on Apple USB keyboards */ set_bit(EV_REP, hi->input->evbit); hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN); diff --git a/drivers/hid/hid-bigbenff.c b/drivers/hid/hid-bigbenff.c index 3f6abd190df4..db6da21ade06 100644 --- a/drivers/hid/hid-bigbenff.c +++ b/drivers/hid/hid-bigbenff.c @@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = { struct bigben_device { struct hid_device *hid; struct hid_report *report; + bool removed; u8 led_state; /* LED1 = 1 .. LED4 = 8 */ u8 right_motor_on; /* right motor off/on 0/1 */ u8 left_motor_force; /* left motor force 0-255 */ @@ -190,6 +191,9 @@ static void bigben_worker(struct work_struct *work) struct bigben_device, worker); struct hid_field *report_field = bigben->report->field[0]; + if (bigben->removed) + return; + if (bigben->work_led) { bigben->work_led = false; report_field->value[0] = 0x01; /* 1 = led message */ @@ -220,10 +224,16 @@ static void bigben_worker(struct work_struct *work) static int hid_bigben_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { - struct bigben_device *bigben = data; + struct hid_device *hid = input_get_drvdata(dev); + struct bigben_device *bigben = hid_get_drvdata(hid); u8 right_motor_on; u8 left_motor_force; + if (!bigben) { + hid_err(hid, "no device data\n"); + return 0; + } + if (effect->type != FF_RUMBLE) return 0; @@ -298,8 +308,8 @@ static void bigben_remove(struct hid_device *hid) { struct bigben_device *bigben = hid_get_drvdata(hid); + bigben->removed = true; cancel_work_sync(&bigben->worker); - hid_hw_close(hid); hid_hw_stop(hid); } @@ -319,6 +329,7 @@ static int bigben_probe(struct hid_device *hid, return -ENOMEM; hid_set_drvdata(hid, bigben); bigben->hid = hid; + bigben->removed = false; error = hid_parse(hid); if (error) { @@ -341,10 +352,10 @@ static int bigben_probe(struct hid_device *hid, INIT_WORK(&bigben->worker, bigben_worker); - error = input_ff_create_memless(hidinput->input, bigben, + error = input_ff_create_memless(hidinput->input, NULL, hid_bigben_play_effect); if (error) - return error; + goto error_hw_stop; name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1; @@ -354,8 +365,10 @@ static int bigben_probe(struct hid_device *hid, sizeof(struct led_classdev) + name_sz, GFP_KERNEL ); - if (!led) - return -ENOMEM; + if (!led) { + error = -ENOMEM; + goto error_hw_stop; + } name = (void *)(&led[1]); snprintf(name, name_sz, "%s:red:bigben%d", @@ -369,7 +382,7 @@ static int bigben_probe(struct hid_device *hid, bigben->leds[n] = led; error = devm_led_classdev_register(&hid->dev, led); if (error) - return error; + goto error_hw_stop; } /* initial state: LED1 is on, no rumble effect */ @@ -383,6 +396,10 @@ static int bigben_probe(struct hid_device *hid, hid_info(hid, "LED and force feedback support for BigBen gamepad\n"); return 0; + +error_hw_stop: + hid_hw_stop(hid); + return error; } static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc, diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c index d86a9189e88f..aeb351658ad3 100644 --- a/drivers/hid/hid-google-hammer.c +++ b/drivers/hid/hid-google-hammer.c @@ -473,6 +473,8 @@ static const struct hid_device_id hammer_devices[] = { USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MASTERBALL) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MOONBALL) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 1515cb1b97c3..0e4018ceaccf 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -478,6 +478,7 @@ #define USB_DEVICE_ID_GOOGLE_WHISKERS 0x5030 #define USB_DEVICE_ID_GOOGLE_MASTERBALL 0x503c #define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d +#define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044 #define USB_VENDOR_ID_GOTOP 0x08f2 #define USB_DEVICE_ID_SUPER_Q2 0x007f @@ -726,6 +727,7 @@ #define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085 #define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3 #define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5 +#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d #define USB_VENDOR_ID_LG 0x1fd2 #define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 8955f96a3af7..144e936f77ab 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -103,6 +103,7 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL }, + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET }, diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c index d31ea82b84c1..a66f08041a1a 100644 --- a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c +++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c @@ -341,6 +341,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { }, .driver_data = (void *)&sipodev_desc }, + { + .ident = "Trekstor SURFBOOK E11B", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SURFBOOK E11B"), + }, + .driver_data = (void *)&sipodev_desc + }, { .ident = "Direkt-Tek DTLAPY116-2", .matches = { diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 9632e2e3c4bb..319a0519ebdb 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -413,7 +413,7 @@ static int ADT7462_REG_VOLT(struct adt7462_data *data, int which) return 0x95; break; } - return -ENODEV; + return 0; } /* Provide labels for sysfs */ diff --git a/drivers/hwtracing/intel_th/msu.c b/drivers/hwtracing/intel_th/msu.c index 8e48c7458aa3..255f8f41c8ff 100644 --- a/drivers/hwtracing/intel_th/msu.c +++ b/drivers/hwtracing/intel_th/msu.c @@ -718,9 +718,6 @@ static int msc_win_set_lockout(struct msc_window *win, if (old != expect) { ret = -EINVAL; - dev_warn_ratelimited(msc_dev(win->msc), - "expected lockout state %d, got %d\n", - expect, old); goto unlock; } @@ -741,6 +738,10 @@ unlock: /* from intel_th_msc_window_unlock(), don't warn if not locked */ if (expect == WIN_LOCKED && old == new) return 0; + + dev_warn_ratelimited(msc_dev(win->msc), + "expected lockout state %d, got %d\n", + expect, old); } return ret; @@ -760,7 +761,7 @@ static int msc_configure(struct msc *msc) lockdep_assert_held(&msc->buf_mutex); if (msc->mode > MSC_MODE_MULTI) - return -ENOTSUPP; + return -EINVAL; if (msc->mode == MSC_MODE_MULTI) { if (msc_win_set_lockout(msc->cur_win, WIN_READY, WIN_INUSE)) @@ -1294,7 +1295,7 @@ static int msc_buffer_alloc(struct msc *msc, unsigned long *nr_pages, } else if (msc->mode == MSC_MODE_MULTI) { ret = msc_buffer_multi_alloc(msc, nr_pages, nr_wins); } else { - ret = -ENOTSUPP; + ret = -EINVAL; } if (!ret) { @@ -1530,7 +1531,7 @@ static ssize_t intel_th_msc_read(struct file *file, char __user *buf, if (ret >= 0) *ppos = iter->offset; } else { - ret = -ENOTSUPP; + ret = -EINVAL; } put_count: diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c index e9d90b53bbc4..86aa6a46bcba 100644 --- a/drivers/hwtracing/intel_th/pci.c +++ b/drivers/hwtracing/intel_th/pci.c @@ -234,6 +234,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6), .driver_data = (kernel_ulong_t)&intel_th_2x, }, + { + /* Elkhart Lake CPU */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4529), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, { /* Elkhart Lake */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26), diff --git a/drivers/hwtracing/stm/p_sys-t.c b/drivers/hwtracing/stm/p_sys-t.c index b178a5495b67..360b5c03df95 100644 --- a/drivers/hwtracing/stm/p_sys-t.c +++ b/drivers/hwtracing/stm/p_sys-t.c @@ -238,7 +238,7 @@ static struct configfs_attribute *sys_t_policy_attrs[] = { static inline bool sys_t_need_ts(struct sys_t_output *op) { if (op->node.ts_interval && - time_after(op->ts_jiffies + op->node.ts_interval, jiffies)) { + time_after(jiffies, op->ts_jiffies + op->node.ts_interval)) { op->ts_jiffies = jiffies; return true; @@ -250,8 +250,8 @@ static inline bool sys_t_need_ts(struct sys_t_output *op) static bool sys_t_need_clock_sync(struct sys_t_output *op) { if (op->node.clocksync_interval && - time_after(op->clocksync_jiffies + op->node.clocksync_interval, - jiffies)) { + time_after(jiffies, + op->clocksync_jiffies + op->node.clocksync_interval)) { op->clocksync_jiffies = jiffies; return true; diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 050adda7c1bd..05b35ac33ce3 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -313,6 +313,7 @@ static void i2c_dw_pci_remove(struct pci_dev *pdev) pm_runtime_get_noresume(&pdev->dev); i2c_del_adapter(&dev->adapter); + devm_free_irq(&pdev->dev, dev->irq, dev); pci_free_irq_vectors(pdev); } diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 3a9e840a3546..a4a6825c8758 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -348,7 +348,7 @@ static struct gpio_desc *i2c_gpio_get_desc(struct device *dev, if (ret == -ENOENT) retdesc = ERR_PTR(-EPROBE_DEFER); - if (ret != -EPROBE_DEFER) + if (PTR_ERR(retdesc) != -EPROBE_DEFER) dev_err(dev, "error trying to get descriptor: %d\n", ret); return retdesc; diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index 8497c7a95dd4..224f830f77f9 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -477,6 +477,7 @@ static int hix5hd2_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&priv->adap); pm_runtime_disable(priv->dev); pm_runtime_set_suspended(priv->dev); + clk_disable_unprepare(priv->clk); return 0; } diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c index 5a1235fd86bb..32cd62188a3d 100644 --- a/drivers/i2c/busses/i2c-nvidia-gpu.c +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -75,20 +76,15 @@ static void gpu_enable_i2c_bus(struct gpu_i2c_dev *i2cd) static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd) { - unsigned long target = jiffies + msecs_to_jiffies(1000); u32 val; + int ret; - do { - val = readl(i2cd->regs + I2C_MST_CNTL); - if (!(val & I2C_MST_CNTL_CYCLE_TRIGGER)) - break; - if ((val & I2C_MST_CNTL_STATUS) != - I2C_MST_CNTL_STATUS_BUS_BUSY) - break; - usleep_range(500, 600); - } while (time_is_after_jiffies(target)); + ret = readl_poll_timeout(i2cd->regs + I2C_MST_CNTL, val, + !(val & I2C_MST_CNTL_CYCLE_TRIGGER) || + (val & I2C_MST_CNTL_STATUS) != I2C_MST_CNTL_STATUS_BUS_BUSY, + 500, 1000 * USEC_PER_MSEC); - if (time_is_before_jiffies(target)) { + if (ret) { dev_err(i2cd->dev, "i2c timeout error %x\n", val); return -ETIMEDOUT; } diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 62a1c92ab803..ce70b5288472 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -394,9 +394,17 @@ EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle); static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev) { struct device *dev; + struct i2c_client *client; dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev); - return dev ? i2c_verify_client(dev) : NULL; + if (!dev) + return NULL; + + client = i2c_verify_client(dev); + if (!client) + put_device(dev); + + return client; } static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value, diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c index 67b8817995c0..60daf04ce188 100644 --- a/drivers/iio/accel/adxl372.c +++ b/drivers/iio/accel/adxl372.c @@ -237,6 +237,7 @@ static const struct adxl372_axis_lookup adxl372_axis_lookup_table[] = { .realbits = 12, \ .storagebits = 16, \ .shift = 4, \ + .endianness = IIO_BE, \ }, \ } diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c index 50fa0fc32baa..0a0bffe04217 100644 --- a/drivers/iio/accel/st_accel_i2c.c +++ b/drivers/iio/accel/st_accel_i2c.c @@ -114,7 +114,7 @@ MODULE_DEVICE_TABLE(of, st_accel_of_match); #ifdef CONFIG_ACPI static const struct acpi_device_id st_accel_acpi_match[] = { - {"SMO8840", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME}, + {"SMO8840", (kernel_ulong_t)LIS2DH12_ACCEL_DEV_NAME}, {"SMO8A90", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME}, { }, }; diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index a2837a0e7cba..2c01963a6a5c 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -723,6 +723,7 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) { struct iio_chan_spec const *chan = at91_adc_chan_get(indio, bit); + u32 cor; if (!chan) continue; @@ -731,6 +732,20 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) chan->type == IIO_PRESSURE) continue; + if (state) { + cor = at91_adc_readl(st, AT91_SAMA5D2_COR); + + if (chan->differential) + cor |= (BIT(chan->channel) | + BIT(chan->channel2)) << + AT91_SAMA5D2_COR_DIFF_OFFSET; + else + cor &= ~(BIT(chan->channel) << + AT91_SAMA5D2_COR_DIFF_OFFSET); + + at91_adc_writel(st, AT91_SAMA5D2_COR, cor); + } + if (state) { at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel)); diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c index 0339ecdd06bd..3ae0366a7b58 100644 --- a/drivers/iio/adc/stm32-dfsdm-adc.c +++ b/drivers/iio/adc/stm32-dfsdm-adc.c @@ -842,31 +842,6 @@ static inline void stm32_dfsdm_process_data(struct stm32_dfsdm_adc *adc, } } -static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); - int available = stm32_dfsdm_adc_dma_residue(adc); - - while (available >= indio_dev->scan_bytes) { - s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi]; - - stm32_dfsdm_process_data(adc, buffer); - - iio_push_to_buffers_with_timestamp(indio_dev, buffer, - pf->timestamp); - available -= indio_dev->scan_bytes; - adc->bufi += indio_dev->scan_bytes; - if (adc->bufi >= adc->buf_sz) - adc->bufi = 0; - } - - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - static void stm32_dfsdm_dma_buffer_done(void *data) { struct iio_dev *indio_dev = data; @@ -874,11 +849,6 @@ static void stm32_dfsdm_dma_buffer_done(void *data) int available = stm32_dfsdm_adc_dma_residue(adc); size_t old_pos; - if (indio_dev->currentmode & INDIO_BUFFER_TRIGGERED) { - iio_trigger_poll_chained(indio_dev->trig); - return; - } - /* * FIXME: In Kernel interface does not support cyclic DMA buffer,and * offers only an interface to push data samples per samples. @@ -906,7 +876,15 @@ static void stm32_dfsdm_dma_buffer_done(void *data) adc->bufi = 0; old_pos = 0; } - /* regular iio buffer without trigger */ + /* + * In DMA mode the trigger services of IIO are not used + * (e.g. no call to iio_trigger_poll). + * Calling irq handler associated to the hardware trigger is not + * relevant as the conversions have already been done. Data + * transfers are performed directly in DMA callback instead. + * This implementation avoids to call trigger irq handler that + * may sleep, in an atomic context (DMA irq handler context). + */ if (adc->dev_data->type == DFSDM_IIO) iio_push_to_buffers(indio_dev, buffer); } @@ -1517,8 +1495,7 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev) } ret = iio_triggered_buffer_setup(indio_dev, - &iio_pollfunc_store_time, - &stm32_dfsdm_adc_trigger_handler, + &iio_pollfunc_store_time, NULL, &stm32_dfsdm_buffer_setup_ops); if (ret) { stm32_dfsdm_dma_release(indio_dev); diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index 0b91de4df8f4..a7e65a59bf42 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -91,6 +91,8 @@ config SPS30 tristate "SPS30 particulate matter sensor" depends on I2C select CRC8 + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say Y here to build support for the Sensirion SPS30 particulate matter sensor. diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index b0e241aaefb4..e5b00a6611ac 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -167,16 +167,17 @@ static int vcnl4200_init(struct vcnl4000_data *data) data->vcnl4200_ps.reg = VCNL4200_PS_DATA; switch (id) { case VCNL4200_PROD_ID: - /* Integration time is 50ms, but the experiments */ - /* show 54ms in total. */ - data->vcnl4200_al.sampling_rate = ktime_set(0, 54000 * 1000); - data->vcnl4200_ps.sampling_rate = ktime_set(0, 4200 * 1000); + /* Default wait time is 50ms, add 20% tolerance. */ + data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000); + /* Default wait time is 4.8ms, add 20% tolerance. */ + data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000); data->al_scale = 24000; break; case VCNL4040_PROD_ID: - /* Integration time is 80ms, add 10ms. */ - data->vcnl4200_al.sampling_rate = ktime_set(0, 100000 * 1000); - data->vcnl4200_ps.sampling_rate = ktime_set(0, 100000 * 1000); + /* Default wait time is 80ms, add 20% tolerance. */ + data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000); + /* Default wait time is 5ms, add 20% tolerance. */ + data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000); data->al_scale = 120000; break; } diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index fc7e910f8e8b..d32996702110 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -564,7 +564,7 @@ static int ak8974_read_raw(struct iio_dev *indio_dev, * We read all axes and discard all but one, for optimized * reading, use the triggered buffer. */ - *val = le16_to_cpu(hw_values[chan->address]); + *val = (s16)le16_to_cpu(hw_values[chan->address]); ret = IIO_VAL_INT; } diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index a5dfe65cd9b9..f98510c714b5 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -161,7 +161,8 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv, return 0; } -static void stm32_timer_stop(struct stm32_timer_trigger *priv) +static void stm32_timer_stop(struct stm32_timer_trigger *priv, + struct iio_trigger *trig) { u32 ccer, cr1; @@ -179,6 +180,12 @@ static void stm32_timer_stop(struct stm32_timer_trigger *priv) regmap_write(priv->regmap, TIM_PSC, 0); regmap_write(priv->regmap, TIM_ARR, 0); + /* Force disable master mode */ + if (stm32_timer_is_trgo2_name(trig->name)) + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0); + else + regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0); + /* Make sure that registers are updated */ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG); } @@ -197,7 +204,7 @@ static ssize_t stm32_tt_store_frequency(struct device *dev, return ret; if (freq == 0) { - stm32_timer_stop(priv); + stm32_timer_stop(priv, trig); } else { ret = stm32_timer_start(priv, trig, freq); if (ret) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 5920c0085d35..319e4b4ae639 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -1228,6 +1228,7 @@ struct ib_cm_id *ib_cm_insert_listen(struct ib_device *device, /* Sharing an ib_cm_id with different handlers is not * supported */ spin_unlock_irqrestore(&cm.lock, flags); + ib_destroy_cm_id(cm_id); return ERR_PTR(-EINVAL); } atomic_inc(&cm_id_priv->refcount); diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9008937f8ed8..6c12da176981 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3155,19 +3155,26 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, int ret; id_priv = container_of(id, struct rdma_id_private, id); + memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); if (id_priv->state == RDMA_CM_IDLE) { ret = cma_bind_addr(id, src_addr, dst_addr); - if (ret) + if (ret) { + memset(cma_dst_addr(id_priv), 0, + rdma_addr_size(dst_addr)); return ret; + } } - if (cma_family(id_priv) != dst_addr->sa_family) + if (cma_family(id_priv) != dst_addr->sa_family) { + memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr)); return -EINVAL; + } - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) + if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) { + memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr)); return -EINVAL; + } - memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); if (cma_any_addr(dst_addr)) { ret = cma_resolve_loopback(id_priv); } else { diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index 9b30773f2da0..86a17a87f181 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -338,6 +338,21 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev, qp->pd = pd; qp->uobject = uobj; qp->real_qp = qp; + + qp->qp_type = attr->qp_type; + qp->qp_context = attr->qp_context; + qp->rwq_ind_tbl = attr->rwq_ind_tbl; + qp->send_cq = attr->send_cq; + qp->recv_cq = attr->recv_cq; + qp->srq = attr->srq; + qp->rwq_ind_tbl = attr->rwq_ind_tbl; + qp->event_handler = attr->event_handler; + + atomic_set(&qp->usecnt, 0); + spin_lock_init(&qp->mr_lock); + INIT_LIST_HEAD(&qp->rdma_mrs); + INIT_LIST_HEAD(&qp->sig_mrs); + /* * We don't track XRC QPs for now, because they don't have PD * and more importantly they are created internaly by driver, diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 2a770b8dca00..10ae6c6eab0a 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -899,7 +899,9 @@ static int add_one_compat_dev(struct ib_device *device, cdev->dev.parent = device->dev.parent; rdma_init_coredev(cdev, device, read_pnet(&rnet->net)); cdev->dev.release = compatdev_release; - dev_set_name(&cdev->dev, "%s", dev_name(&device->dev)); + ret = dev_set_name(&cdev->dev, "%s", dev_name(&device->dev)); + if (ret) + goto add_err; ret = device_add(&cdev->dev); if (ret) diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index ade71823370f..da8adadf4755 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -159,8 +159,10 @@ static void dealloc_work_entries(struct iwcm_id_private *cm_id_priv) { struct list_head *e, *tmp; - list_for_each_safe(e, tmp, &cm_id_priv->work_free_list) + list_for_each_safe(e, tmp, &cm_id_priv->work_free_list) { + list_del(e); kfree(list_entry(e, struct iwcm_work, free_list)); + } } static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count) diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index c03af08b80e7..ef4b0c7061e4 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -863,6 +863,10 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh, nla_strlcpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME], IB_DEVICE_NAME_MAX); + if (strlen(name) == 0) { + err = -EINVAL; + goto done; + } err = ib_device_rename(device, name); goto done; } @@ -1468,7 +1472,7 @@ static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME], sizeof(ibdev_name)); - if (strchr(ibdev_name, '%')) + if (strchr(ibdev_name, '%') || strlen(ibdev_name) == 0) return -EINVAL; nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type)); @@ -1711,6 +1715,8 @@ static int nldev_stat_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh, if (ret) goto err_msg; } else { + if (!tb[RDMA_NLDEV_ATTR_RES_LQPN]) + goto err_msg; qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]); if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]) { cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]); diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c index 5337393d4dfe..bb10cbfa0070 100644 --- a/drivers/infiniband/core/rw.c +++ b/drivers/infiniband/core/rw.c @@ -268,6 +268,23 @@ static int rdma_rw_init_single_wr(struct rdma_rw_ctx *ctx, struct ib_qp *qp, return 1; } +static void rdma_rw_unmap_sg(struct ib_device *dev, struct scatterlist *sg, + u32 sg_cnt, enum dma_data_direction dir) +{ + if (is_pci_p2pdma_page(sg_page(sg))) + pci_p2pdma_unmap_sg(dev->dma_device, sg, sg_cnt, dir); + else + ib_dma_unmap_sg(dev, sg, sg_cnt, dir); +} + +static int rdma_rw_map_sg(struct ib_device *dev, struct scatterlist *sg, + u32 sg_cnt, enum dma_data_direction dir) +{ + if (is_pci_p2pdma_page(sg_page(sg))) + return pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir); + return ib_dma_map_sg(dev, sg, sg_cnt, dir); +} + /** * rdma_rw_ctx_init - initialize a RDMA READ/WRITE context * @ctx: context to initialize @@ -290,11 +307,7 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num, struct ib_device *dev = qp->pd->device; int ret; - if (is_pci_p2pdma_page(sg_page(sg))) - ret = pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir); - else - ret = ib_dma_map_sg(dev, sg, sg_cnt, dir); - + ret = rdma_rw_map_sg(dev, sg, sg_cnt, dir); if (!ret) return -ENOMEM; sg_cnt = ret; @@ -333,7 +346,7 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num, return ret; out_unmap_sg: - ib_dma_unmap_sg(dev, sg, sg_cnt, dir); + rdma_rw_unmap_sg(dev, sg, sg_cnt, dir); return ret; } EXPORT_SYMBOL(rdma_rw_ctx_init); @@ -583,11 +596,7 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num, break; } - if (is_pci_p2pdma_page(sg_page(sg))) - pci_p2pdma_unmap_sg(qp->pd->device->dma_device, sg, - sg_cnt, dir); - else - ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir); + rdma_rw_unmap_sg(qp->pd->device, sg, sg_cnt, dir); } EXPORT_SYMBOL(rdma_rw_ctx_destroy); diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c index 2b4d80393bd0..75e7ec017836 100644 --- a/drivers/infiniband/core/security.c +++ b/drivers/infiniband/core/security.c @@ -340,20 +340,19 @@ static struct ib_ports_pkeys *get_new_pps(const struct ib_qp *qp, return NULL; if (qp_attr_mask & IB_QP_PORT) - new_pps->main.port_num = - (qp_pps) ? qp_pps->main.port_num : qp_attr->port_num; - if (qp_attr_mask & IB_QP_PKEY_INDEX) - new_pps->main.pkey_index = (qp_pps) ? qp_pps->main.pkey_index : - qp_attr->pkey_index; - if ((qp_attr_mask & IB_QP_PKEY_INDEX) && (qp_attr_mask & IB_QP_PORT)) - new_pps->main.state = IB_PORT_PKEY_VALID; - - if (!(qp_attr_mask & (IB_QP_PKEY_INDEX || IB_QP_PORT)) && qp_pps) { + new_pps->main.port_num = qp_attr->port_num; + else if (qp_pps) new_pps->main.port_num = qp_pps->main.port_num; + + if (qp_attr_mask & IB_QP_PKEY_INDEX) + new_pps->main.pkey_index = qp_attr->pkey_index; + else if (qp_pps) new_pps->main.pkey_index = qp_pps->main.pkey_index; - if (qp_pps->main.state != IB_PORT_PKEY_NOT_VALID) - new_pps->main.state = IB_PORT_PKEY_VALID; - } + + if (((qp_attr_mask & IB_QP_PKEY_INDEX) && + (qp_attr_mask & IB_QP_PORT)) || + (qp_pps && qp_pps->main.state != IB_PORT_PKEY_NOT_VALID)) + new_pps->main.state = IB_PORT_PKEY_VALID; if (qp_attr_mask & IB_QP_ALT_PATH) { new_pps->alt.port_num = qp_attr->alt_port_num; diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 1235ffb2389b..da229eab5903 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -1129,17 +1129,30 @@ static const struct file_operations umad_sm_fops = { .llseek = no_llseek, }; +static struct ib_umad_port *get_port(struct ib_device *ibdev, + struct ib_umad_device *umad_dev, + unsigned int port) +{ + if (!umad_dev) + return ERR_PTR(-EOPNOTSUPP); + if (!rdma_is_port_valid(ibdev, port)) + return ERR_PTR(-EINVAL); + if (!rdma_cap_ib_mad(ibdev, port)) + return ERR_PTR(-EOPNOTSUPP); + + return &umad_dev->ports[port - rdma_start_port(ibdev)]; +} + static int ib_umad_get_nl_info(struct ib_device *ibdev, void *client_data, struct ib_client_nl_info *res) { - struct ib_umad_device *umad_dev = client_data; + struct ib_umad_port *port = get_port(ibdev, client_data, res->port); - if (!rdma_is_port_valid(ibdev, res->port)) - return -EINVAL; + if (IS_ERR(port)) + return PTR_ERR(port); res->abi = IB_USER_MAD_ABI_VERSION; - res->cdev = &umad_dev->ports[res->port - rdma_start_port(ibdev)].dev; - + res->cdev = &port->dev; return 0; } @@ -1154,15 +1167,13 @@ MODULE_ALIAS_RDMA_CLIENT("umad"); static int ib_issm_get_nl_info(struct ib_device *ibdev, void *client_data, struct ib_client_nl_info *res) { - struct ib_umad_device *umad_dev = - ib_get_client_data(ibdev, &umad_client); + struct ib_umad_port *port = get_port(ibdev, client_data, res->port); - if (!rdma_is_port_valid(ibdev, res->port)) - return -EINVAL; + if (IS_ERR(port)) + return PTR_ERR(port); res->abi = IB_USER_MAD_ABI_VERSION; - res->cdev = &umad_dev->ports[res->port - rdma_start_port(ibdev)].sm_dev; - + res->cdev = &port->sm_dev; return 0; } diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 300353c1e5f1..e2ddcb0dc4ee 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1431,17 +1431,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs, if (ret) goto err_cb; - qp->pd = pd; - qp->send_cq = attr.send_cq; - qp->recv_cq = attr.recv_cq; - qp->srq = attr.srq; - qp->rwq_ind_tbl = ind_tbl; - qp->event_handler = attr.event_handler; - qp->qp_context = attr.qp_context; - qp->qp_type = attr.qp_type; - atomic_set(&qp->usecnt, 0); atomic_inc(&pd->usecnt); - qp->port = 0; if (attr.send_cq) atomic_inc(&attr.send_cq->usecnt); if (attr.recv_cq) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 35c2841a569e..6c4093d0a91d 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -1180,16 +1180,6 @@ struct ib_qp *ib_create_qp_user(struct ib_pd *pd, if (ret) goto err; - qp->qp_type = qp_init_attr->qp_type; - qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl; - - atomic_set(&qp->usecnt, 0); - qp->mrs_used = 0; - spin_lock_init(&qp->mr_lock); - INIT_LIST_HEAD(&qp->rdma_mrs); - INIT_LIST_HEAD(&qp->sig_mrs); - qp->port = 0; - if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) { struct ib_qp *xrc_qp = create_xrc_qp_user(qp, qp_init_attr, udata); diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index 089e201d7550..2f6323ad9c59 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -515,10 +515,11 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet, opa_get_lid(packet->dlid, 9B)); if (!mcast) goto drop; + rcu_read_lock(); list_for_each_entry_rcu(p, &mcast->qp_list, list) { packet->qp = p->qp; if (hfi1_do_pkey_check(packet)) - goto drop; + goto unlock_drop; spin_lock_irqsave(&packet->qp->r_lock, flags); packet_handler = qp_ok(packet); if (likely(packet_handler)) @@ -527,6 +528,7 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet, ibp->rvp.n_pkt_drops++; spin_unlock_irqrestore(&packet->qp->r_lock, flags); } + rcu_read_unlock(); /* * Notify rvt_multicast_detach() if it is waiting for us * to finish. diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c index 45f48cde6b9d..ff664355de55 100644 --- a/drivers/infiniband/hw/mlx5/cq.c +++ b/drivers/infiniband/hw/mlx5/cq.c @@ -330,6 +330,22 @@ static void mlx5_handle_error_cqe(struct mlx5_ib_dev *dev, dump_cqe(dev, cqe); } +static void handle_atomics(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64, + u16 tail, u16 head) +{ + u16 idx; + + do { + idx = tail & (qp->sq.wqe_cnt - 1); + if (idx == head) + break; + + tail = qp->sq.w_list[idx].next; + } while (1); + tail = qp->sq.w_list[idx].next; + qp->sq.last_poll = tail; +} + static void free_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf) { mlx5_frag_buf_free(dev->mdev, &buf->frag_buf); @@ -368,7 +384,7 @@ static void get_sig_err_item(struct mlx5_sig_err_cqe *cqe, } static void sw_comp(struct mlx5_ib_qp *qp, int num_entries, struct ib_wc *wc, - int *npolled, int is_send) + int *npolled, bool is_send) { struct mlx5_ib_wq *wq; unsigned int cur; @@ -383,10 +399,16 @@ static void sw_comp(struct mlx5_ib_qp *qp, int num_entries, struct ib_wc *wc, return; for (i = 0; i < cur && np < num_entries; i++) { - wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)]; + unsigned int idx; + + idx = (is_send) ? wq->last_poll : wq->tail; + idx &= (wq->wqe_cnt - 1); + wc->wr_id = wq->wrid[idx]; wc->status = IB_WC_WR_FLUSH_ERR; wc->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR; wq->tail++; + if (is_send) + wq->last_poll = wq->w_list[idx].next; np++; wc->qp = &qp->ibqp; wc++; @@ -476,6 +498,7 @@ repoll: wqe_ctr = be16_to_cpu(cqe64->wqe_counter); idx = wqe_ctr & (wq->wqe_cnt - 1); handle_good_req(wc, cqe64, wq, idx); + handle_atomics(*cur_qp, cqe64, wq->last_poll, idx); wc->wr_id = wq->wrid[idx]; wq->tail = wq->wqe_head[idx] + 1; wc->status = IB_WC_SUCCESS; diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 9a918db9e8db..0a160fd1383a 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -5638,9 +5638,10 @@ mlx5_ib_counter_alloc_stats(struct rdma_counter *counter) const struct mlx5_ib_counters *cnts = get_counters(dev, counter->port - 1); - /* Q counters are in the beginning of all counters */ return rdma_alloc_hw_stats_struct(cnts->names, - cnts->num_q_counters, + cnts->num_q_counters + + cnts->num_cong_counters + + cnts->num_ext_ppcnt_counters, RDMA_HW_STATS_DEFAULT_LIFESPAN); } diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 1a98ee2e01c4..a9ce46c4c1ae 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -283,6 +283,7 @@ struct mlx5_ib_wq { unsigned head; unsigned tail; u16 cur_post; + u16 last_poll; void *cur_edge; }; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 0865373bd12d..881decb1309a 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -3725,6 +3725,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp, qp->sq.cur_post = 0; if (qp->sq.wqe_cnt) qp->sq.cur_edge = get_sq_edge(&qp->sq, 0); + qp->sq.last_poll = 0; qp->db.db[MLX5_RCV_DBR] = 0; qp->db.db[MLX5_SND_DBR] = 0; } @@ -6131,6 +6132,10 @@ struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd, if (udata->outlen && udata->outlen < min_resp_len) return ERR_PTR(-EINVAL); + if (!capable(CAP_SYS_RAWIO) && + init_attr->create_flags & IB_WQ_FLAGS_DELAY_DROP) + return ERR_PTR(-EPERM); + dev = to_mdev(pd->device); switch (init_attr->wq_type) { case IB_WQT_RQ: diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 33778d451b82..5ef93f8f17a1 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c @@ -329,8 +329,10 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen) if (mcast == NULL) goto drop; this_cpu_inc(ibp->pmastats->n_multicast_rcv); + rcu_read_lock(); list_for_each_entry_rcu(p, &mcast->qp_list, list) qib_qp_rcv(rcd, hdr, 1, data, tlen, p->qp); + rcu_read_unlock(); /* * Notify rvt_multicast_detach() if it is waiting for us * to finish. diff --git a/drivers/infiniband/sw/rdmavt/cq.c b/drivers/infiniband/sw/rdmavt/cq.c index a85571a4cf57..0fee3c87776b 100644 --- a/drivers/infiniband/sw/rdmavt/cq.c +++ b/drivers/infiniband/sw/rdmavt/cq.c @@ -327,7 +327,7 @@ void rvt_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) if (cq->ip) kref_put(&cq->ip->ref, rvt_release_mmap_info); else - vfree(cq->queue); + vfree(cq->kqueue); } /** diff --git a/drivers/infiniband/sw/siw/siw_main.c b/drivers/infiniband/sw/siw/siw_main.c index fb01407a310f..130b1e31b978 100644 --- a/drivers/infiniband/sw/siw/siw_main.c +++ b/drivers/infiniband/sw/siw/siw_main.c @@ -379,6 +379,9 @@ static struct siw_device *siw_device_create(struct net_device *netdev) base_dev->dev.dma_ops = &dma_virt_ops; base_dev->num_comp_vectors = num_possible_cpus(); + xa_init_flags(&sdev->qp_xa, XA_FLAGS_ALLOC1); + xa_init_flags(&sdev->mem_xa, XA_FLAGS_ALLOC1); + ib_set_device_ops(base_dev, &siw_device_ops); rv = ib_device_set_netdev(base_dev, netdev, 1); if (rv) @@ -406,9 +409,6 @@ static struct siw_device *siw_device_create(struct net_device *netdev) sdev->attrs.max_srq_wr = SIW_MAX_SRQ_WR; sdev->attrs.max_srq_sge = SIW_MAX_SGE; - xa_init_flags(&sdev->qp_xa, XA_FLAGS_ALLOC1); - xa_init_flags(&sdev->mem_xa, XA_FLAGS_ALLOC1); - INIT_LIST_HEAD(&sdev->cep_list); INIT_LIST_HEAD(&sdev->qp_list); diff --git a/drivers/input/input.c b/drivers/input/input.c index ee6c3234df36..e2eb9b9b8363 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -190,6 +190,7 @@ static void input_repeat_key(struct timer_list *t) input_value_sync }; + input_set_timestamp(dev, ktime_get()); input_pass_values(dev, vals, ARRAY_SIZE(vals)); if (dev->rep[REP_PERIOD]) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 2c666fb34625..4d2036209b45 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -186,6 +186,7 @@ static const char * const smbus_pnp_ids[] = { "SYN3052", /* HP EliteBook 840 G4 */ "SYN3221", /* HP 15-ay000 */ "SYN323d", /* HP Spectre X360 13-w013dx */ + "SYN3257", /* HP Envy 13-ad105ng */ NULL }; diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 6ed9f22e6401..fe245439adee 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -432,7 +432,7 @@ static int raydium_i2c_write_object(struct i2c_client *client, return 0; } -static bool raydium_i2c_boot_trigger(struct i2c_client *client) +static int raydium_i2c_boot_trigger(struct i2c_client *client) { static const u8 cmd[7][6] = { { 0x08, 0x0C, 0x09, 0x00, 0x50, 0xD7 }, @@ -457,10 +457,10 @@ static bool raydium_i2c_boot_trigger(struct i2c_client *client) } } - return false; + return 0; } -static bool raydium_i2c_fw_trigger(struct i2c_client *client) +static int raydium_i2c_fw_trigger(struct i2c_client *client) { static const u8 cmd[5][11] = { { 0, 0x09, 0x71, 0x0C, 0x09, 0x00, 0x50, 0xD7, 0, 0, 0 }, @@ -483,7 +483,7 @@ static bool raydium_i2c_fw_trigger(struct i2c_client *client) } } - return false; + return 0; } static int raydium_i2c_check_path(struct i2c_client *client) diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile index 0f918d54a607..d52a62c70dd4 100644 --- a/drivers/interconnect/Makefile +++ b/drivers/interconnect/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 +CFLAGS_core.o := -I$(src) icc-core-objs := core.o icc-test-objs := debugfs-test.o diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 415c85d3e665..d87dabdf9ff0 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -21,6 +21,9 @@ #include "internal.h" +#define CREATE_TRACE_POINTS +#include "trace.h" + static DEFINE_IDR(icc_idr); static LIST_HEAD(icc_providers); static DEFINE_MUTEX(icc_lock); @@ -420,9 +423,22 @@ struct icc_path *of_icc_get(struct device *dev, const char *name) mutex_lock(&icc_lock); path = path_find(dev, src_node, dst_node); - if (IS_ERR(path)) - dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); mutex_unlock(&icc_lock); + if (IS_ERR(path)) { + dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); + return path; + } + + if (name) + path->name = kstrdup_const(name, GFP_KERNEL); + else + path->name = kasprintf(GFP_KERNEL, "%s-%s", + src_node->name, dst_node->name); + + if (!path->name) { + kfree(path); + return ERR_PTR(-ENOMEM); + } return path; } @@ -491,6 +507,8 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) /* aggregate requests for this node */ aggregate_requests(node); + + trace_icc_set_bw(path, node, i, avg_bw, peak_bw); } ret = apply_constraints(path); @@ -509,6 +527,8 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) mutex_unlock(&icc_lock); + trace_icc_set_bw_end(path, ret); + return ret; } EXPORT_SYMBOL_GPL(icc_set_bw); @@ -545,9 +565,16 @@ struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id) goto out; path = path_find(dev, src, dst); - if (IS_ERR(path)) + if (IS_ERR(path)) { dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); + goto out; + } + path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name); + if (!path->name) { + kfree(path); + path = ERR_PTR(-ENOMEM); + } out: mutex_unlock(&icc_lock); return path; @@ -583,6 +610,7 @@ void icc_put(struct icc_path *path) } mutex_unlock(&icc_lock); + kfree_const(path->name); kfree(path); } EXPORT_SYMBOL_GPL(icc_put); diff --git a/drivers/interconnect/internal.h b/drivers/interconnect/internal.h index 5853e8faf223..bf18cb7239df 100644 --- a/drivers/interconnect/internal.h +++ b/drivers/interconnect/internal.h @@ -29,10 +29,12 @@ struct icc_req { /** * struct icc_path - interconnect path structure + * @name: a string name of the path (useful for ftrace) * @num_nodes: number of hops (nodes) * @reqs: array of the requests applicable to this path of nodes */ struct icc_path { + const char *name; size_t num_nodes; struct icc_req reqs[]; }; diff --git a/drivers/interconnect/trace.h b/drivers/interconnect/trace.h new file mode 100644 index 000000000000..3d668ff566bf --- /dev/null +++ b/drivers/interconnect/trace.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Interconnect framework tracepoints + * Copyright (c) 2019, Linaro Ltd. + * Author: Georgi Djakov + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM interconnect + +#if !defined(_TRACE_INTERCONNECT_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_INTERCONNECT_H + +#include +#include + +TRACE_EVENT(icc_set_bw, + + TP_PROTO(struct icc_path *p, struct icc_node *n, int i, + u32 avg_bw, u32 peak_bw), + + TP_ARGS(p, n, i, avg_bw, peak_bw), + + TP_STRUCT__entry( + __string(path_name, p->name) + __string(dev, dev_name(p->reqs[i].dev)) + __string(node_name, n->name) + __field(u32, avg_bw) + __field(u32, peak_bw) + __field(u32, node_avg_bw) + __field(u32, node_peak_bw) + ), + + TP_fast_assign( + __assign_str(path_name, p->name); + __assign_str(dev, dev_name(p->reqs[i].dev)); + __assign_str(node_name, n->name); + __entry->avg_bw = avg_bw; + __entry->peak_bw = peak_bw; + __entry->node_avg_bw = n->avg_bw; + __entry->node_peak_bw = n->peak_bw; + ), + + TP_printk("path=%s dev=%s node=%s avg_bw=%u peak_bw=%u agg_avg=%u agg_peak=%u", + __get_str(path_name), + __get_str(dev), + __get_str(node_name), + __entry->avg_bw, + __entry->peak_bw, + __entry->node_avg_bw, + __entry->node_peak_bw) +); + +TRACE_EVENT(icc_set_bw_end, + + TP_PROTO(struct icc_path *p, int ret), + + TP_ARGS(p, ret), + + TP_STRUCT__entry( + __string(path_name, p->name) + __string(dev, dev_name(p->reqs[0].dev)) + __field(int, ret) + ), + + TP_fast_assign( + __assign_str(path_name, p->name); + __assign_str(dev, dev_name(p->reqs[0].dev)); + __entry->ret = ret; + ), + + TP_printk("path=%s dev=%s ret=%d", + __get_str(path_name), + __get_str(dev), + __entry->ret) +); + +#endif /* _TRACE_INTERCONNECT_H */ + +/* This part must be outside protection */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . + +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +#include diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 8bd5d608a82c..bc7771498342 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -4421,7 +4421,7 @@ int amd_iommu_activate_guest_mode(void *data) entry->lo.fields_vapic.ga_tag = ir_data->ga_tag; return modify_irte_ga(ir_data->irq_2_irte.devid, - ir_data->irq_2_irte.index, entry, NULL); + ir_data->irq_2_irte.index, entry, ir_data); } EXPORT_SYMBOL(amd_iommu_activate_guest_mode); @@ -4447,7 +4447,7 @@ int amd_iommu_deactivate_guest_mode(void *data) APICID_TO_IRTE_DEST_HI(cfg->dest_apicid); return modify_irte_ga(ir_data->irq_2_irte.devid, - ir_data->irq_2_irte.index, entry, NULL); + ir_data->irq_2_irte.index, entry, ir_data); } EXPORT_SYMBOL(amd_iommu_deactivate_guest_mode); diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index d7cbca8bf2cd..b5ae9f7c0510 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2533,6 +2533,7 @@ static int __init early_amd_iommu_init(void) struct acpi_table_header *ivrs_base; acpi_status status; int i, remap_cache_sz, ret = 0; + u32 pci_id; if (!amd_iommu_detected) return -ENODEV; @@ -2620,6 +2621,16 @@ static int __init early_amd_iommu_init(void) if (ret) goto out; + /* Disable IOMMU if there's Stoney Ridge graphics */ + for (i = 0; i < 32; i++) { + pci_id = read_pci_config(0, i, 0, 0); + if ((pci_id & 0xffff) == 0x1002 && (pci_id >> 16) == 0x98e4) { + pr_info("Disable IOMMU on Stoney Ridge\n"); + amd_iommu_disabled = true; + break; + } + } + /* Disable any previously enabled IOMMUs */ if (!is_kdump_kernel() || amd_iommu_disabled) disable_iommus(); @@ -2728,7 +2739,7 @@ static int __init state_next(void) ret = early_amd_iommu_init(); init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED; if (init_state == IOMMU_ACPI_FINISHED && amd_iommu_disabled) { - pr_info("AMD IOMMU disabled on kernel command-line\n"); + pr_info("AMD IOMMU disabled\n"); init_state = IOMMU_CMDLINE_DISABLED; ret = -EINVAL; } diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index f708eb80247f..f9f68da841a1 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -178,15 +178,15 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie, start -= iova_offset(iovad, start); num_pages = iova_align(iovad, end - start) >> iova_shift(iovad); - msi_page = kcalloc(num_pages, sizeof(*msi_page), GFP_KERNEL); - if (!msi_page) - return -ENOMEM; - for (i = 0; i < num_pages; i++) { - msi_page[i].phys = start; - msi_page[i].iova = start; - INIT_LIST_HEAD(&msi_page[i].list); - list_add(&msi_page[i].list, &cookie->msi_page_list); + msi_page = kmalloc(sizeof(*msi_page), GFP_KERNEL); + if (!msi_page) + return -ENOMEM; + + msi_page->phys = start; + msi_page->iova = start; + INIT_LIST_HEAD(&msi_page->list); + list_add(&msi_page->list, &cookie->msi_page_list); start += iovad->granule; } diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 7196cabafb25..9e393b9c5091 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,13 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) BUG_ON(dev->is_virtfn); + /* + * Ignore devices that have a domain number higher than what can + * be looked up in DMAR, e.g. VMD subdevices with domain 0x10000 + */ + if (pci_domain_nr(dev->bus) > U16_MAX) + return NULL; + /* Only generate path[] for device addition event */ if (event == BUS_NOTIFY_ADD_DEVICE) for (tmp = dev; tmp; tmp = tmp->bus->self) @@ -363,7 +371,8 @@ dmar_find_dmaru(struct acpi_dmar_hardware_unit *drhd) { struct dmar_drhd_unit *dmaru; - list_for_each_entry_rcu(dmaru, &dmar_drhd_units, list) + list_for_each_entry_rcu(dmaru, &dmar_drhd_units, list, + dmar_rcu_check()) if (dmaru->segment == drhd->segment && dmaru->reg_base_addr == drhd->address) return dmaru; @@ -440,12 +449,13 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header, /* Check for NUL termination within the designated length */ if (strnlen(andd->device_name, header->length - 8) == header->length - 8) { - WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, + pr_warn(FW_BUG "Your BIOS is broken; ANDD object name is not NUL-terminated\n" "BIOS vendor: %s; Ver: %s; Product Version: %s\n", dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); return -EINVAL; } pr_info("ANDD device: %x name: %s\n", andd->device_number, @@ -471,14 +481,14 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg) return 0; } } - WARN_TAINT( - 1, TAINT_FIRMWARE_WORKAROUND, + pr_warn(FW_BUG "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - drhd->reg_base_addr, + rhsa->base_address, dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); return 0; } @@ -827,14 +837,14 @@ int __init dmar_table_init(void) static void warn_invalid_dmar(u64 addr, const char *message) { - WARN_TAINT_ONCE( - 1, TAINT_FIRMWARE_WORKAROUND, + pr_warn_once(FW_BUG "Your BIOS is broken; DMAR reported at address %llx%s!\n" "BIOS vendor: %s; Ver: %s; Product Version: %s\n", addr, message, dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_PRODUCT_VERSION)); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); } static int __ref diff --git a/drivers/iommu/intel-iommu-debugfs.c b/drivers/iommu/intel-iommu-debugfs.c index 471f05d452e0..bdf095e9dbe0 100644 --- a/drivers/iommu/intel-iommu-debugfs.c +++ b/drivers/iommu/intel-iommu-debugfs.c @@ -32,38 +32,42 @@ struct iommu_regset { #define IOMMU_REGSET_ENTRY(_reg_) \ { DMAR_##_reg_##_REG, __stringify(_reg_) } -static const struct iommu_regset iommu_regs[] = { + +static const struct iommu_regset iommu_regs_32[] = { IOMMU_REGSET_ENTRY(VER), - IOMMU_REGSET_ENTRY(CAP), - IOMMU_REGSET_ENTRY(ECAP), IOMMU_REGSET_ENTRY(GCMD), IOMMU_REGSET_ENTRY(GSTS), - IOMMU_REGSET_ENTRY(RTADDR), - IOMMU_REGSET_ENTRY(CCMD), IOMMU_REGSET_ENTRY(FSTS), IOMMU_REGSET_ENTRY(FECTL), IOMMU_REGSET_ENTRY(FEDATA), IOMMU_REGSET_ENTRY(FEADDR), IOMMU_REGSET_ENTRY(FEUADDR), - IOMMU_REGSET_ENTRY(AFLOG), IOMMU_REGSET_ENTRY(PMEN), IOMMU_REGSET_ENTRY(PLMBASE), IOMMU_REGSET_ENTRY(PLMLIMIT), - IOMMU_REGSET_ENTRY(PHMBASE), - IOMMU_REGSET_ENTRY(PHMLIMIT), - IOMMU_REGSET_ENTRY(IQH), - IOMMU_REGSET_ENTRY(IQT), - IOMMU_REGSET_ENTRY(IQA), IOMMU_REGSET_ENTRY(ICS), - IOMMU_REGSET_ENTRY(IRTA), - IOMMU_REGSET_ENTRY(PQH), - IOMMU_REGSET_ENTRY(PQT), - IOMMU_REGSET_ENTRY(PQA), IOMMU_REGSET_ENTRY(PRS), IOMMU_REGSET_ENTRY(PECTL), IOMMU_REGSET_ENTRY(PEDATA), IOMMU_REGSET_ENTRY(PEADDR), IOMMU_REGSET_ENTRY(PEUADDR), +}; + +static const struct iommu_regset iommu_regs_64[] = { + IOMMU_REGSET_ENTRY(CAP), + IOMMU_REGSET_ENTRY(ECAP), + IOMMU_REGSET_ENTRY(RTADDR), + IOMMU_REGSET_ENTRY(CCMD), + IOMMU_REGSET_ENTRY(AFLOG), + IOMMU_REGSET_ENTRY(PHMBASE), + IOMMU_REGSET_ENTRY(PHMLIMIT), + IOMMU_REGSET_ENTRY(IQH), + IOMMU_REGSET_ENTRY(IQT), + IOMMU_REGSET_ENTRY(IQA), + IOMMU_REGSET_ENTRY(IRTA), + IOMMU_REGSET_ENTRY(PQH), + IOMMU_REGSET_ENTRY(PQT), + IOMMU_REGSET_ENTRY(PQA), IOMMU_REGSET_ENTRY(MTRRCAP), IOMMU_REGSET_ENTRY(MTRRDEF), IOMMU_REGSET_ENTRY(MTRR_FIX64K_00000), @@ -126,10 +130,16 @@ static int iommu_regset_show(struct seq_file *m, void *unused) * by adding the offset to the pointer (virtual address). */ raw_spin_lock_irqsave(&iommu->register_lock, flag); - for (i = 0 ; i < ARRAY_SIZE(iommu_regs); i++) { - value = dmar_readq(iommu->reg + iommu_regs[i].offset); + for (i = 0 ; i < ARRAY_SIZE(iommu_regs_32); i++) { + value = dmar_readl(iommu->reg + iommu_regs_32[i].offset); seq_printf(m, "%-16s\t0x%02x\t\t0x%016llx\n", - iommu_regs[i].regs, iommu_regs[i].offset, + iommu_regs_32[i].regs, iommu_regs_32[i].offset, + value); + } + for (i = 0 ; i < ARRAY_SIZE(iommu_regs_64); i++) { + value = dmar_readq(iommu->reg + iommu_regs_64[i].offset); + seq_printf(m, "%-16s\t0x%02x\t\t0x%016llx\n", + iommu_regs_64[i].regs, iommu_regs_64[i].offset, value); } raw_spin_unlock_irqrestore(&iommu->register_lock, flag); @@ -271,9 +281,16 @@ static int dmar_translation_struct_show(struct seq_file *m, void *unused) { struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; + u32 sts; rcu_read_lock(); for_each_active_iommu(iommu, drhd) { + sts = dmar_readl(iommu->reg + DMAR_GSTS_REG); + if (!(sts & DMA_GSTS_TES)) { + seq_printf(m, "DMA Remapping is not enabled on %s\n", + iommu->name); + continue; + } root_tbl_walk(m, iommu); seq_putc(m, '\n'); } @@ -343,6 +360,7 @@ static int ir_translation_struct_show(struct seq_file *m, void *unused) struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; u64 irta; + u32 sts; rcu_read_lock(); for_each_active_iommu(iommu, drhd) { @@ -352,7 +370,8 @@ static int ir_translation_struct_show(struct seq_file *m, void *unused) seq_printf(m, "Remapped Interrupt supported on IOMMU: %s\n", iommu->name); - if (iommu->ir_table) { + sts = dmar_readl(iommu->reg + DMAR_GSTS_REG); + if (iommu->ir_table && (sts & DMA_GSTS_IRES)) { irta = virt_to_phys(iommu->ir_table->base); seq_printf(m, " IR table address:%llx\n", irta); ir_tbl_remap_entry_show(m, iommu); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 760a242d0801..9d47b227e557 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4129,10 +4129,11 @@ static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev) /* we know that the this iommu should be at offset 0xa000 from vtbar */ drhd = dmar_find_matched_drhd_unit(pdev); - if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000, - TAINT_FIRMWARE_WORKAROUND, - "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n")) + if (!drhd || drhd->reg_base_addr - vtbar != 0xa000) { + pr_warn_once(FW_BUG "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; + } } DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu); @@ -4960,6 +4961,9 @@ int __init intel_iommu_init(void) down_write(&dmar_global_lock); + if (!no_iommu) + intel_iommu_debugfs_init(); + if (no_iommu || dmar_disabled) { /* * We exit the function here to ensure IOMMU's remapping and @@ -5023,6 +5027,7 @@ int __init intel_iommu_init(void) init_iommu_pm_ops(); + down_read(&dmar_global_lock); for_each_active_iommu(iommu, drhd) { iommu_device_sysfs_add(&iommu->iommu, NULL, intel_iommu_groups, @@ -5030,6 +5035,7 @@ int __init intel_iommu_init(void) iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops); iommu_device_register(&iommu->iommu); } + up_read(&dmar_global_lock); bus_set_iommu(&pci_bus_type, &intel_iommu_ops); if (si_domain && !hw_pass_through) @@ -5040,7 +5046,6 @@ int __init intel_iommu_init(void) down_read(&dmar_global_lock); if (probe_acpi_namespace_devices()) pr_warn("ACPI name space devices didn't probe correctly\n"); - up_read(&dmar_global_lock); /* Finally, we enable the DMA remapping hardware. */ for_each_iommu(iommu, drhd) { @@ -5049,10 +5054,11 @@ int __init intel_iommu_init(void) iommu_disable_protect_mem_regions(iommu); } + up_read(&dmar_global_lock); + pr_info("Intel(R) Virtualization Technology for Directed I/O\n"); intel_iommu_enabled = 1; - intel_iommu_debugfs_init(); return 0; @@ -5523,8 +5529,10 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, u64 phys = 0; pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level); - if (pte) - phys = dma_pte_addr(pte); + if (pte && dma_pte_present(pte)) + phys = dma_pte_addr(pte) + + (iova & (BIT_MASK(level_to_offset_bits(level) + + VTD_PAGE_SHIFT) - 1)); return phys; } diff --git a/drivers/macintosh/windfarm_ad7417_sensor.c b/drivers/macintosh/windfarm_ad7417_sensor.c index 125605987b44..e7dec328c7cf 100644 --- a/drivers/macintosh/windfarm_ad7417_sensor.c +++ b/drivers/macintosh/windfarm_ad7417_sensor.c @@ -312,9 +312,16 @@ static const struct i2c_device_id wf_ad7417_id[] = { }; MODULE_DEVICE_TABLE(i2c, wf_ad7417_id); +static const struct of_device_id wf_ad7417_of_id[] = { + { .compatible = "ad7417", }, + { } +}; +MODULE_DEVICE_TABLE(of, wf_ad7417_of_id); + static struct i2c_driver wf_ad7417_driver = { .driver = { .name = "wf_ad7417", + .of_match_table = wf_ad7417_of_id, }, .probe = wf_ad7417_probe, .remove = wf_ad7417_remove, diff --git a/drivers/macintosh/windfarm_fcu_controls.c b/drivers/macintosh/windfarm_fcu_controls.c index 3c971297b6dc..89b48e8ac6ef 100644 --- a/drivers/macintosh/windfarm_fcu_controls.c +++ b/drivers/macintosh/windfarm_fcu_controls.c @@ -582,9 +582,16 @@ static const struct i2c_device_id wf_fcu_id[] = { }; MODULE_DEVICE_TABLE(i2c, wf_fcu_id); +static const struct of_device_id wf_fcu_of_id[] = { + { .compatible = "fcu", }, + { } +}; +MODULE_DEVICE_TABLE(of, wf_fcu_of_id); + static struct i2c_driver wf_fcu_driver = { .driver = { .name = "wf_fcu", + .of_match_table = wf_fcu_of_id, }, .probe = wf_fcu_probe, .remove = wf_fcu_remove, diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 282c28a17ea1..1e5fa09845e7 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -91,9 +92,14 @@ static int wf_lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct wf_lm75_sensor *lm; - int rc, ds1775 = id->driver_data; + int rc, ds1775; const char *name, *loc; + if (id) + ds1775 = id->driver_data; + else + ds1775 = !!of_device_get_match_data(&client->dev); + DBG("wf_lm75: creating %s device at address 0x%02x\n", ds1775 ? "ds1775" : "lm75", client->addr); @@ -164,9 +170,17 @@ static const struct i2c_device_id wf_lm75_id[] = { }; MODULE_DEVICE_TABLE(i2c, wf_lm75_id); +static const struct of_device_id wf_lm75_of_id[] = { + { .compatible = "lm75", .data = (void *)0}, + { .compatible = "ds1775", .data = (void *)1 }, + { } +}; +MODULE_DEVICE_TABLE(of, wf_lm75_of_id); + static struct i2c_driver wf_lm75_driver = { .driver = { .name = "wf_lm75", + .of_match_table = wf_lm75_of_id, }, .probe = wf_lm75_probe, .remove = wf_lm75_remove, diff --git a/drivers/macintosh/windfarm_lm87_sensor.c b/drivers/macintosh/windfarm_lm87_sensor.c index e44525b19071..1a1f8f3f0abc 100644 --- a/drivers/macintosh/windfarm_lm87_sensor.c +++ b/drivers/macintosh/windfarm_lm87_sensor.c @@ -166,9 +166,16 @@ static const struct i2c_device_id wf_lm87_id[] = { }; MODULE_DEVICE_TABLE(i2c, wf_lm87_id); +static const struct of_device_id wf_lm87_of_id[] = { + { .compatible = "lm87cimt", }, + { } +}; +MODULE_DEVICE_TABLE(of, wf_lm87_of_id); + static struct i2c_driver wf_lm87_driver = { .driver = { .name = "wf_lm87", + .of_match_table = wf_lm87_of_id, }, .probe = wf_lm87_probe, .remove = wf_lm87_remove, diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index e666cc020683..1e7b03d44ad9 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -120,9 +120,16 @@ static const struct i2c_device_id wf_max6690_id[] = { }; MODULE_DEVICE_TABLE(i2c, wf_max6690_id); +static const struct of_device_id wf_max6690_of_id[] = { + { .compatible = "max6690", }, + { } +}; +MODULE_DEVICE_TABLE(of, wf_max6690_of_id); + static struct i2c_driver wf_max6690_driver = { .driver = { .name = "wf_max6690", + .of_match_table = wf_max6690_of_id, }, .probe = wf_max6690_probe, .remove = wf_max6690_remove, diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index c84ec49c3741..cb75dc035616 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -341,9 +341,16 @@ static const struct i2c_device_id wf_sat_id[] = { }; MODULE_DEVICE_TABLE(i2c, wf_sat_id); +static const struct of_device_id wf_sat_of_id[] = { + { .compatible = "smu-sat", }, + { } +}; +MODULE_DEVICE_TABLE(of, wf_sat_of_id); + static struct i2c_driver wf_sat_driver = { .driver = { .name = "wf_smu_sat", + .of_match_table = wf_sat_of_id, }, .probe = wf_sat_probe, .remove = wf_sat_remove, diff --git a/drivers/md/dm-bio-record.h b/drivers/md/dm-bio-record.h index c82578af56a5..2ea0360108e1 100644 --- a/drivers/md/dm-bio-record.h +++ b/drivers/md/dm-bio-record.h @@ -20,8 +20,13 @@ struct dm_bio_details { struct gendisk *bi_disk; u8 bi_partno; + int __bi_remaining; unsigned long bi_flags; struct bvec_iter bi_iter; + bio_end_io_t *bi_end_io; +#if defined(CONFIG_BLK_DEV_INTEGRITY) + struct bio_integrity_payload *bi_integrity; +#endif }; static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio) @@ -30,6 +35,11 @@ static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio) bd->bi_partno = bio->bi_partno; bd->bi_flags = bio->bi_flags; bd->bi_iter = bio->bi_iter; + bd->__bi_remaining = atomic_read(&bio->__bi_remaining); + bd->bi_end_io = bio->bi_end_io; +#if defined(CONFIG_BLK_DEV_INTEGRITY) + bd->bi_integrity = bio_integrity(bio); +#endif } static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio) @@ -38,6 +48,11 @@ static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio) bio->bi_partno = bd->bi_partno; bio->bi_flags = bd->bi_flags; bio->bi_iter = bd->bi_iter; + atomic_set(&bio->__bi_remaining, bd->__bi_remaining); + bio->bi_end_io = bd->bi_end_io; +#if defined(CONFIG_BLK_DEV_INTEGRITY) + bio->bi_integrity = bd->bi_integrity; +#endif } #endif diff --git a/drivers/md/dm-bow.c b/drivers/md/dm-bow.c index ee0e2b6fe450..75fc7dc83d7b 100644 --- a/drivers/md/dm-bow.c +++ b/drivers/md/dm-bow.c @@ -792,6 +792,7 @@ static int prepare_unchanged_range(struct bow_context *bc, struct bow_range *br, */ original_type = br->type; sector0 = backup_br->sector; + bc->trims_total -= range_size(backup_br); if (backup_br->type == TRIMMED) list_del(&backup_br->trimmed_list); backup_br->type = br->type == SECTOR0_CURRENT ? SECTOR0_CURRENT diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 8346e6d1816c..f595e9867cbe 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2867,8 +2867,8 @@ static void cache_postsuspend(struct dm_target *ti) prevent_background_work(cache); BUG_ON(atomic_read(&cache->nr_io_migrations)); - cancel_delayed_work(&cache->waker); - flush_workqueue(cache->wq); + cancel_delayed_work_sync(&cache->waker); + drain_workqueue(cache->wq); WARN_ON(cache->tracker.in_flight); /* diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index dab4446fe7d8..145bc2e7eaf0 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -6,6 +6,8 @@ * This file is released under the GPL. */ +#include "dm-bio-record.h" + #include #include #include @@ -199,17 +201,19 @@ struct dm_integrity_c { __u8 log2_blocks_per_bitmap_bit; unsigned char mode; - int suspending; int failed; struct crypto_shash *internal_hash; + struct dm_target *ti; + /* these variables are locked with endio_wait.lock */ struct rb_root in_progress; struct list_head wait_list; wait_queue_head_t endio_wait; struct workqueue_struct *wait_wq; + struct workqueue_struct *offload_wq; unsigned char commit_seq; commit_id_t commit_ids[N_COMMIT_IDS]; @@ -290,11 +294,7 @@ struct dm_integrity_io { struct completion *completion; - struct gendisk *orig_bi_disk; - u8 orig_bi_partno; - bio_end_io_t *orig_bi_end_io; - struct bio_integrity_payload *orig_bi_integrity; - struct bvec_iter orig_bi_iter; + struct dm_bio_details bio_details; }; struct journal_completion { @@ -1434,7 +1434,7 @@ static void dec_in_flight(struct dm_integrity_io *dio) dio->range.logical_sector += dio->range.n_sectors; bio_advance(bio, dio->range.n_sectors << SECTOR_SHIFT); INIT_WORK(&dio->work, integrity_bio_wait); - queue_work(ic->wait_wq, &dio->work); + queue_work(ic->offload_wq, &dio->work); return; } do_endio_flush(ic, dio); @@ -1445,14 +1445,9 @@ static void integrity_end_io(struct bio *bio) { struct dm_integrity_io *dio = dm_per_bio_data(bio, sizeof(struct dm_integrity_io)); - bio->bi_iter = dio->orig_bi_iter; - bio->bi_disk = dio->orig_bi_disk; - bio->bi_partno = dio->orig_bi_partno; - if (dio->orig_bi_integrity) { - bio->bi_integrity = dio->orig_bi_integrity; + dm_bio_restore(&dio->bio_details, bio); + if (bio->bi_integrity) bio->bi_opf |= REQ_INTEGRITY; - } - bio->bi_end_io = dio->orig_bi_end_io; if (dio->completion) complete(dio->completion); @@ -1537,7 +1532,7 @@ static void integrity_metadata(struct work_struct *w) } } - __bio_for_each_segment(bv, bio, iter, dio->orig_bi_iter) { + __bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) { unsigned pos; char *mem, *checksums_ptr; @@ -1581,7 +1576,7 @@ again: if (likely(checksums != checksums_onstack)) kfree(checksums); } else { - struct bio_integrity_payload *bip = dio->orig_bi_integrity; + struct bio_integrity_payload *bip = dio->bio_details.bi_integrity; if (bip) { struct bio_vec biv; @@ -1860,7 +1855,7 @@ static void dm_integrity_map_continue(struct dm_integrity_io *dio, bool from_map if (need_sync_io && from_map) { INIT_WORK(&dio->work, integrity_bio_wait); - queue_work(ic->metadata_wq, &dio->work); + queue_work(ic->offload_wq, &dio->work); return; } @@ -2000,20 +1995,13 @@ offload_to_thread: } else dio->completion = NULL; - dio->orig_bi_iter = bio->bi_iter; - - dio->orig_bi_disk = bio->bi_disk; - dio->orig_bi_partno = bio->bi_partno; + dm_bio_record(&dio->bio_details, bio); bio_set_dev(bio, ic->dev->bdev); - - dio->orig_bi_integrity = bio_integrity(bio); bio->bi_integrity = NULL; bio->bi_opf &= ~REQ_INTEGRITY; - - dio->orig_bi_end_io = bio->bi_end_io; bio->bi_end_io = integrity_end_io; - bio->bi_iter.bi_size = dio->range.n_sectors << SECTOR_SHIFT; + generic_make_request(bio); if (need_sync_io) { @@ -2310,7 +2298,7 @@ static void integrity_writer(struct work_struct *w) unsigned prev_free_sectors; /* the following test is not needed, but it tests the replay code */ - if (READ_ONCE(ic->suspending) && !ic->meta_dev) + if (unlikely(dm_suspended(ic->ti)) && !ic->meta_dev) return; spin_lock_irq(&ic->endio_wait.lock); @@ -2371,7 +2359,7 @@ static void integrity_recalc(struct work_struct *w) next_chunk: - if (unlikely(READ_ONCE(ic->suspending))) + if (unlikely(dm_suspended(ic->ti))) goto unlock_ret; range.logical_sector = le64_to_cpu(ic->sb->recalc_sector); @@ -2496,7 +2484,7 @@ static void bitmap_block_work(struct work_struct *w) dio->range.n_sectors, BITMAP_OP_TEST_ALL_SET)) { remove_range(ic, &dio->range); INIT_WORK(&dio->work, integrity_bio_wait); - queue_work(ic->wait_wq, &dio->work); + queue_work(ic->offload_wq, &dio->work); } else { block_bitmap_op(ic, ic->journal, dio->range.logical_sector, dio->range.n_sectors, BITMAP_OP_SET); @@ -2519,7 +2507,7 @@ static void bitmap_block_work(struct work_struct *w) remove_range(ic, &dio->range); INIT_WORK(&dio->work, integrity_bio_wait); - queue_work(ic->wait_wq, &dio->work); + queue_work(ic->offload_wq, &dio->work); } queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, ic->bitmap_flush_interval); @@ -2799,8 +2787,6 @@ static void dm_integrity_postsuspend(struct dm_target *ti) del_timer_sync(&ic->autocommit_timer); - WRITE_ONCE(ic->suspending, 1); - if (ic->recalc_wq) drain_workqueue(ic->recalc_wq); @@ -2829,8 +2815,6 @@ static void dm_integrity_postsuspend(struct dm_target *ti) #endif } - WRITE_ONCE(ic->suspending, 0); - BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress)); ic->journal_uptodate = true; @@ -2883,17 +2867,24 @@ static void dm_integrity_resume(struct dm_target *ti) } else { replay_journal(ic); if (ic->mode == 'B') { - int mode; ic->sb->flags |= cpu_to_le32(SB_FLAG_DIRTY_BITMAP); ic->sb->log2_blocks_per_bitmap_bit = ic->log2_blocks_per_bitmap_bit; r = sync_rw_sb(ic, REQ_OP_WRITE, REQ_FUA); if (unlikely(r)) dm_integrity_io_error(ic, "writing superblock", r); - mode = ic->recalculate_flag ? BITMAP_OP_SET : BITMAP_OP_CLEAR; - block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, mode); - block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, mode); - block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, mode); + block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR); + block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR); + block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR); + if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) && + le64_to_cpu(ic->sb->recalc_sector) < ic->provided_data_sectors) { + block_bitmap_op(ic, ic->journal, le64_to_cpu(ic->sb->recalc_sector), + ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET); + block_bitmap_op(ic, ic->recalc_bitmap, le64_to_cpu(ic->sb->recalc_sector), + ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET); + block_bitmap_op(ic, ic->may_write_bitmap, le64_to_cpu(ic->sb->recalc_sector), + ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET); + } rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, 0, ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL); } @@ -2961,7 +2952,7 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type, DMEMIT(" meta_device:%s", ic->meta_dev->name); if (ic->sectors_per_block != 1) DMEMIT(" block_size:%u", ic->sectors_per_block << SECTOR_SHIFT); - if (ic->recalculate_flag) + if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) DMEMIT(" recalculate"); DMEMIT(" journal_sectors:%u", ic->initial_sectors - SB_SECTORS); DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors); @@ -3607,6 +3598,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv) } ti->private = ic; ti->per_io_data_size = sizeof(struct dm_integrity_io); + ic->ti = ti; ic->in_progress = RB_ROOT; INIT_LIST_HEAD(&ic->wait_list); @@ -3818,6 +3810,14 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv) goto bad; } + ic->offload_wq = alloc_workqueue("dm-integrity-offload", WQ_MEM_RECLAIM, + METADATA_WORKQUEUE_MAX_ACTIVE); + if (!ic->offload_wq) { + ti->error = "Cannot allocate workqueue"; + r = -ENOMEM; + goto bad; + } + ic->commit_wq = alloc_workqueue("dm-integrity-commit", WQ_MEM_RECLAIM, 1); if (!ic->commit_wq) { ti->error = "Cannot allocate workqueue"; @@ -4122,6 +4122,8 @@ static void dm_integrity_dtr(struct dm_target *ti) destroy_workqueue(ic->metadata_wq); if (ic->wait_wq) destroy_workqueue(ic->wait_wq); + if (ic->offload_wq) + destroy_workqueue(ic->offload_wq); if (ic->commit_wq) destroy_workqueue(ic->commit_wq); if (ic->writer_wq) diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 8bb723f1a569..4cd8868f8004 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c @@ -960,9 +960,9 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd) DMWARN("%s: __commit_transaction() failed, error = %d", __func__, r); } + pmd_write_unlock(pmd); if (!pmd->fail_io) __destroy_persistent_data_objects(pmd); - pmd_write_unlock(pmd); kfree(pmd); return 0; diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c index 07c1b0334f57..184dabce1bad 100644 --- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -625,6 +625,12 @@ static void writecache_add_to_freelist(struct dm_writecache *wc, struct wc_entry wc->freelist_size++; } +static inline void writecache_verify_watermark(struct dm_writecache *wc) +{ + if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark)) + queue_work(wc->writeback_wq, &wc->writeback_work); +} + static struct wc_entry *writecache_pop_from_freelist(struct dm_writecache *wc) { struct wc_entry *e; @@ -646,8 +652,8 @@ static struct wc_entry *writecache_pop_from_freelist(struct dm_writecache *wc) list_del(&e->lru); } wc->freelist_size--; - if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark)) - queue_work(wc->writeback_wq, &wc->writeback_work); + + writecache_verify_watermark(wc); return e; } @@ -838,7 +844,7 @@ static void writecache_suspend(struct dm_target *ti) } wc_unlock(wc); - flush_workqueue(wc->writeback_wq); + drain_workqueue(wc->writeback_wq); wc_lock(wc); if (flush_on_suspend) @@ -961,6 +967,8 @@ erase_this: writecache_commit_flushed(wc, false); } + writecache_verify_watermark(wc); + wc_unlock(wc); } diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c index 70a1063161c0..b1e64cd31647 100644 --- a/drivers/md/dm-zoned-target.c +++ b/drivers/md/dm-zoned-target.c @@ -533,8 +533,9 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio) /* Get the BIO chunk work. If one is not active yet, create one */ cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk); - if (!cw) { - + if (cw) { + dmz_get_chunk_work(cw); + } else { /* Create a new chunk work */ cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO); if (unlikely(!cw)) { @@ -543,7 +544,7 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio) } INIT_WORK(&cw->work, dmz_chunk_work); - refcount_set(&cw->refcount, 0); + refcount_set(&cw->refcount, 1); cw->target = dmz; cw->chunk = chunk; bio_list_init(&cw->bio_list); @@ -556,7 +557,6 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio) } bio_list_add(&cw->bio_list, bio); - dmz_get_chunk_work(cw); dmz_reclaim_bio_acc(dmz->reclaim); if (queue_work(dmz->chunk_wq, &cw->work)) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index e81870588abc..502de5255d3b 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1790,7 +1790,8 @@ static int dm_any_congested(void *congested_data, int bdi_bits) * With request-based DM we only need to check the * top-level queue for congestion. */ - r = md->queue->backing_dev_info->wb.state & bdi_bits; + struct backing_dev_info *bdi = md->queue->backing_dev_info; + r = bdi->wb.congested->state & bdi_bits; } else { map = dm_get_live_table_fast(md); if (map) @@ -1856,15 +1857,6 @@ static const struct dax_operations dm_dax_ops; static void dm_wq_work(struct work_struct *work); -static void dm_init_normal_md_queue(struct mapped_device *md) -{ - /* - * Initialize aspects of queue that aren't relevant for blk-mq - */ - md->queue->backing_dev_info->congested_data = md; - md->queue->backing_dev_info->congested_fn = dm_any_congested; -} - static void dm_destroy_inline_encryption(struct request_queue *q); static void cleanup_mapped_device(struct mapped_device *md) @@ -2410,6 +2402,12 @@ static inline void dm_destroy_inline_encryption(struct request_queue *q) } #endif /* !CONFIG_BLK_INLINE_ENCRYPTION */ +static void dm_init_congested_fn(struct mapped_device *md) +{ + md->queue->backing_dev_info->congested_data = md; + md->queue->backing_dev_info->congested_fn = dm_any_congested; +} + /* * Setup the DM device's queue based on md's type */ @@ -2426,11 +2424,12 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t) DMERR("Cannot initialize queue for request-based dm-mq mapped device"); return r; } + dm_init_congested_fn(md); break; case DM_TYPE_BIO_BASED: case DM_TYPE_DAX_BIO_BASED: case DM_TYPE_NVME_BIO_BASED: - dm_init_normal_md_queue(md); + dm_init_congested_fn(md); break; case DM_TYPE_NONE: WARN_ON_ONCE(true); @@ -2536,6 +2535,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait) map = dm_get_live_table(md, &srcu_idx); if (!dm_suspended_md(md)) { dm_table_presuspend_targets(map); + set_bit(DMF_SUSPENDED, &md->flags); dm_table_postsuspend_targets(map); } /* dm_put_live_table must be before msleep, otherwise deadlock is possible */ diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c index 7c429ce98bae..668770e9f609 100644 --- a/drivers/media/mc/mc-entity.c +++ b/drivers/media/mc/mc-entity.c @@ -639,9 +639,9 @@ int media_get_pad_index(struct media_entity *entity, bool is_sink, return -EINVAL; for (i = 0; i < entity->num_pads; i++) { - if (entity->pads[i].flags == MEDIA_PAD_FL_SINK) + if (entity->pads[i].flags & MEDIA_PAD_FL_SINK) pad_is_sink = true; - else if (entity->pads[i].flags == MEDIA_PAD_FL_SOURCE) + else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE) pad_is_sink = false; else continue; /* This is an error! */ diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c index 3c93d9232c3c..b6e39fbd8ad5 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.c +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c @@ -27,17 +27,17 @@ static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = { { V4L2_PIX_FMT_BGR24, 3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_RGB24, 3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_HSV24, 3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV}, - { V4L2_PIX_FMT_BGR32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, - { V4L2_PIX_FMT_XBGR32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_BGR32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_XBGR32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_ABGR32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, - { V4L2_PIX_FMT_RGB32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, - { V4L2_PIX_FMT_XRGB32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_RGB32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_XRGB32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_ARGB32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, - { V4L2_PIX_FMT_BGRX32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_BGRX32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_BGRA32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, - { V4L2_PIX_FMT_RGBX32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB}, + { V4L2_PIX_FMT_RGBX32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, { V4L2_PIX_FMT_RGBA32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB}, - { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV}, + { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_HSV}, { V4L2_PIX_FMT_GREY, 1, 1, 1, 1, 0, 1, 1, 1, 1, FWHT_FL_PIXENC_RGB}, }; @@ -175,22 +175,14 @@ static int prepare_raw_frame(struct fwht_raw_frame *rf, case V4L2_PIX_FMT_RGB32: case V4L2_PIX_FMT_XRGB32: case V4L2_PIX_FMT_HSV32: - rf->cr = rf->luma + 1; - rf->cb = rf->cr + 2; - rf->luma += 2; - break; - case V4L2_PIX_FMT_BGR32: - case V4L2_PIX_FMT_XBGR32: - rf->cb = rf->luma; - rf->cr = rf->cb + 2; - rf->luma++; - break; case V4L2_PIX_FMT_ARGB32: rf->alpha = rf->luma; rf->cr = rf->luma + 1; rf->cb = rf->cr + 2; rf->luma += 2; break; + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XBGR32: case V4L2_PIX_FMT_ABGR32: rf->cb = rf->luma; rf->cr = rf->cb + 2; @@ -198,10 +190,6 @@ static int prepare_raw_frame(struct fwht_raw_frame *rf, rf->alpha = rf->cr + 1; break; case V4L2_PIX_FMT_BGRX32: - rf->cb = rf->luma + 1; - rf->cr = rf->cb + 2; - rf->luma += 2; - break; case V4L2_PIX_FMT_BGRA32: rf->alpha = rf->luma; rf->cb = rf->luma + 1; @@ -209,10 +197,6 @@ static int prepare_raw_frame(struct fwht_raw_frame *rf, rf->luma += 2; break; case V4L2_PIX_FMT_RGBX32: - rf->cr = rf->luma; - rf->cb = rf->cr + 2; - rf->luma++; - break; case V4L2_PIX_FMT_RGBA32: rf->alpha = rf->luma + 3; rf->cr = rf->luma; diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 039963a7765b..198ddfb8d2b1 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -511,6 +511,9 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb) return ret; } + if (fc_usb->uintf->cur_altsetting->desc.bNumEndpoints < 1) + return -ENODEV; + switch (fc_usb->udev->speed) { case USB_SPEED_LOW: err("cannot handle USB speed because it is too slow."); @@ -544,9 +547,6 @@ static int flexcop_usb_probe(struct usb_interface *intf, struct flexcop_device *fc = NULL; int ret; - if (intf->cur_altsetting->desc.bNumEndpoints < 1) - return -ENODEV; - if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) { err("out of memory\n"); return -ENOMEM; diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index e53c58ab6488..ef62dd6c5ae4 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -818,7 +818,7 @@ int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ - if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1) + if (intf->cur_altsetting->desc.bNumEndpoints < rc_ep + 1) return -ENODEV; purb = usb_alloc_urb(0, GFP_KERNEL); @@ -838,7 +838,7 @@ int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) * Some devices like the Hauppauge NovaTD model 52009 use an interrupt * endpoint, while others use a bulk one. */ - e = &intf->altsetting[0].endpoint[rc_ep].desc; + e = &intf->cur_altsetting->endpoint[rc_ep].desc; if (usb_endpoint_dir_in(e)) { if (usb_endpoint_xfer_bulk(e)) { pipe = usb_rcvbulkpipe(d->udev, rc_ep); diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c index f417dfc0b872..0afe70a3f9a2 100644 --- a/drivers/media/usb/gspca/ov519.c +++ b/drivers/media/usb/gspca/ov519.c @@ -3477,6 +3477,11 @@ static void ov511_mode_init_regs(struct sd *sd) return; } + if (alt->desc.bNumEndpoints < 1) { + sd->gspca_dev.usb_err = -ENODEV; + return; + } + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); @@ -3603,6 +3608,11 @@ static void ov518_mode_init_regs(struct sd *sd) return; } + if (alt->desc.bNumEndpoints < 1) { + sd->gspca_dev.usb_err = -ENODEV; + return; + } + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c index 79653d409951..95673fc0a99c 100644 --- a/drivers/media/usb/gspca/stv06xx/stv06xx.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c @@ -282,6 +282,9 @@ static int stv06xx_start(struct gspca_dev *gspca_dev) return -EIO; } + if (alt->desc.bNumEndpoints < 1) + return -ENODEV; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size); if (err < 0) @@ -306,11 +309,21 @@ out: static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) { + struct usb_interface_cache *intfc; struct usb_host_interface *alt; struct sd *sd = (struct sd *) gspca_dev; + intfc = gspca_dev->dev->actconfig->intf_cache[0]; + + if (intfc->num_altsetting < 2) + return -ENODEV; + + alt = &intfc->altsetting[1]; + + if (alt->desc.bNumEndpoints < 1) + return -ENODEV; + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ - alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); @@ -323,6 +336,10 @@ static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev) struct usb_host_interface *alt; struct sd *sd = (struct sd *) gspca_dev; + /* + * Existence of altsetting and endpoint was verified in + * stv06xx_isoc_init() + */ alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c index 6d1007715ff7..ae382b3b5f7f 100644 --- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c +++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c @@ -185,6 +185,10 @@ static int pb0100_start(struct sd *sd) alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); if (!alt) return -ENODEV; + + if (alt->desc.bNumEndpoints < 1) + return -ENODEV; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); /* If we don't have enough bandwidth use a lower framerate */ diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c index 934a90bd78c2..c579b100f066 100644 --- a/drivers/media/usb/gspca/xirlink_cit.c +++ b/drivers/media/usb/gspca/xirlink_cit.c @@ -1442,6 +1442,9 @@ static int cit_get_packet_size(struct gspca_dev *gspca_dev) return -EIO; } + if (alt->desc.bNumEndpoints < 1) + return -ENODEV; + return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); } @@ -2626,6 +2629,7 @@ static int sd_start(struct gspca_dev *gspca_dev) static int sd_isoc_init(struct gspca_dev *gspca_dev) { + struct usb_interface_cache *intfc; struct usb_host_interface *alt; int max_packet_size; @@ -2641,8 +2645,17 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev) break; } + intfc = gspca_dev->dev->actconfig->intf_cache[0]; + + if (intfc->num_altsetting < 2) + return -ENODEV; + + alt = &intfc->altsetting[1]; + + if (alt->desc.bNumEndpoints < 1) + return -ENODEV; + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ - alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); return 0; @@ -2665,6 +2678,9 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev) break; } + /* + * Existence of altsetting and endpoint was verified in sd_isoc_init() + */ alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); if (packet_size <= min_packet_size) diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c index 5095c380b2c1..ee9c656d121f 100644 --- a/drivers/media/usb/usbtv/usbtv-core.c +++ b/drivers/media/usb/usbtv/usbtv-core.c @@ -56,7 +56,7 @@ int usbtv_set_regs(struct usbtv *usbtv, const u16 regs[][2], int size) ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, index, NULL, 0, 0); + value, index, NULL, 0, USB_CTRL_GET_TIMEOUT); if (ret < 0) return ret; } diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 3d9284a09ee5..b249f037900c 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -800,7 +800,8 @@ static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl) ret = usb_control_msg(usbtv->udev, usb_rcvctrlpipe(usbtv->udev, 0), USBTV_CONTROL_REG, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, USBTV_BASE + 0x0244, (void *)data, 3, 0); + 0, USBTV_BASE + 0x0244, (void *)data, 3, + USB_CTRL_GET_TIMEOUT); if (ret < 0) goto error; } @@ -851,7 +852,7 @@ static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl) ret = usb_control_msg(usbtv->udev, usb_sndctrlpipe(usbtv->udev, 0), USBTV_CONTROL_REG, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, index, (void *)data, size, 0); + 0, index, (void *)data, size, USB_CTRL_SET_TIMEOUT); error: if (ret < 0) diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 63d6b147b21e..41da73ce2e98 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -179,6 +179,7 @@ static void v4l2_subdev_release(struct v4l2_subdev *sd) if (sd->internal_ops && sd->internal_ops->release) sd->internal_ops->release(sd); + sd->devnode = NULL; module_put(owner); } diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 19937dd3c6f6..3d6a6306cec7 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -809,12 +809,12 @@ int v4l2_m2m_register_media_controller(struct v4l2_m2m_dev *m2m_dev, goto err_rel_entity1; /* Connect the three entities */ - ret = media_create_pad_link(m2m_dev->source, 0, &m2m_dev->proc, 1, + ret = media_create_pad_link(m2m_dev->source, 0, &m2m_dev->proc, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) goto err_rel_entity2; - ret = media_create_pad_link(&m2m_dev->proc, 0, &m2m_dev->sink, 0, + ret = media_create_pad_link(&m2m_dev->proc, 1, &m2m_dev->sink, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) goto err_rm_links0; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 5a7f5ef6ecb4..996b3f82b450 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -510,6 +510,12 @@ config WIGIG_SENSING_SPI The output of the driver is CIRs (Channel Impulse Response) which must be processed in user space in order to get meaningful results. +config HISI_HIKEY_USB + tristate "USB functionality of HiSilicon Hikey Platform" + depends on OF && GPIOLIB + help + If you say yes here you get support for usb functionality of HiSilicon Hikey Platform. + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 6ba93951eba7..a2d845bea161 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -63,3 +63,4 @@ obj-$(CONFIG_QSEECOM) += qseecom-mod.o qseecom-mod-y := qseecom.o qseecom-mod-$(CONFIG_COMPAT) += compat_qseecom.o obj-$(CONFIG_WIGIG_SENSING_SPI) += wigig_sensing.o +obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c index 25e5f24b3fec..5bdf57472314 100644 --- a/drivers/misc/altera-stapl/altera.c +++ b/drivers/misc/altera-stapl/altera.c @@ -2112,8 +2112,8 @@ exit_done: return status; } -static int altera_get_note(u8 *p, s32 program_size, - s32 *offset, char *key, char *value, int length) +static int altera_get_note(u8 *p, s32 program_size, s32 *offset, + char *key, char *value, int keylen, int vallen) /* * Gets key and value of NOTE fields in the JBC file. * Can be called in two modes: if offset pointer is NULL, @@ -2170,7 +2170,7 @@ static int altera_get_note(u8 *p, s32 program_size, &p[note_table + (8 * i) + 4])]; if (value != NULL) - strlcpy(value, value_ptr, length); + strlcpy(value, value_ptr, vallen); } } @@ -2189,13 +2189,13 @@ static int altera_get_note(u8 *p, s32 program_size, strlcpy(key, &p[note_strings + get_unaligned_be32( &p[note_table + (8 * i)])], - length); + keylen); if (value != NULL) strlcpy(value, &p[note_strings + get_unaligned_be32( &p[note_table + (8 * i) + 4])], - length); + vallen); *offset = i + 1; } @@ -2449,7 +2449,7 @@ int altera_init(struct altera_config *config, const struct firmware *fw) __func__, (format_version == 2) ? "Jam STAPL" : "pre-standardized Jam 1.1"); while (altera_get_note((u8 *)fw->data, fw->size, - &offset, key, value, 256) == 0) + &offset, key, value, 32, 256) == 0) printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n", __func__, key, value); } diff --git a/drivers/misc/cardreader/rts5227.c b/drivers/misc/cardreader/rts5227.c index 4feed296a327..423fecc19fc4 100644 --- a/drivers/misc/cardreader/rts5227.c +++ b/drivers/misc/cardreader/rts5227.c @@ -394,7 +394,7 @@ static const struct pcr_ops rts522a_pcr_ops = { void rts522a_init_params(struct rtsx_pcr *pcr) { rts5227_init_params(pcr); - + pcr->tx_initial_phase = SET_CLOCK_PHASE(20, 20, 11); pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3; pcr->option.ocp_en = 1; diff --git a/drivers/misc/cardreader/rts5249.c b/drivers/misc/cardreader/rts5249.c index db936e4d6e56..1a81cda948c1 100644 --- a/drivers/misc/cardreader/rts5249.c +++ b/drivers/misc/cardreader/rts5249.c @@ -618,6 +618,7 @@ static const struct pcr_ops rts524a_pcr_ops = { void rts524a_init_params(struct rtsx_pcr *pcr) { rts5249_init_params(pcr); + pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 29, 11); pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF; pcr->option.ltr_l1off_snooze_sspwrgate = LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF; @@ -733,6 +734,7 @@ static const struct pcr_ops rts525a_pcr_ops = { void rts525a_init_params(struct rtsx_pcr *pcr) { rts5249_init_params(pcr); + pcr->tx_initial_phase = SET_CLOCK_PHASE(25, 29, 11); pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF; pcr->option.ltr_l1off_snooze_sspwrgate = LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF; diff --git a/drivers/misc/cardreader/rts5260.c b/drivers/misc/cardreader/rts5260.c index 40a6d199f2ea..c9327bf92d16 100644 --- a/drivers/misc/cardreader/rts5260.c +++ b/drivers/misc/cardreader/rts5260.c @@ -663,7 +663,7 @@ void rts5260_init_params(struct rtsx_pcr *pcr) pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B; pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; pcr->aspm_en = ASPM_L1_EN; - pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16); + pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 29, 11); pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5); pcr->ic_version = rts5260_get_ic_version(pcr); diff --git a/drivers/misc/habanalabs/device.c b/drivers/misc/habanalabs/device.c index 459fee70a597..a7a4fed4d899 100644 --- a/drivers/misc/habanalabs/device.c +++ b/drivers/misc/habanalabs/device.c @@ -600,7 +600,9 @@ int hl_device_set_debug_mode(struct hl_device *hdev, bool enable) goto out; } - hdev->asic_funcs->halt_coresight(hdev); + if (!hdev->hard_reset_pending) + hdev->asic_funcs->halt_coresight(hdev); + hdev->in_debug = 0; goto out; @@ -1185,6 +1187,7 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass) if (hdev->asic_funcs->get_hw_state(hdev) == HL_DEVICE_HW_STATE_DIRTY) { dev_info(hdev->dev, "H/W state is dirty, must reset before initializing\n"); + hdev->asic_funcs->halt_engines(hdev, true); hdev->asic_funcs->hw_fini(hdev, true); } diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index fe3574a83b7c..13b39fd97429 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -869,6 +869,11 @@ void goya_init_dma_qmans(struct hl_device *hdev) */ static void goya_disable_external_queues(struct hl_device *hdev) { + struct goya_device *goya = hdev->asic_specific; + + if (!(goya->hw_cap_initialized & HW_CAP_DMA)) + return; + WREG32(mmDMA_QM_0_GLBL_CFG0, 0); WREG32(mmDMA_QM_1_GLBL_CFG0, 0); WREG32(mmDMA_QM_2_GLBL_CFG0, 0); @@ -930,6 +935,11 @@ static int goya_stop_external_queues(struct hl_device *hdev) { int rc, retval = 0; + struct goya_device *goya = hdev->asic_specific; + + if (!(goya->hw_cap_initialized & HW_CAP_DMA)) + return retval; + rc = goya_stop_queue(hdev, mmDMA_QM_0_GLBL_CFG1, mmDMA_QM_0_CP_STS, @@ -1719,9 +1729,18 @@ void goya_init_tpc_qmans(struct hl_device *hdev) */ static void goya_disable_internal_queues(struct hl_device *hdev) { + struct goya_device *goya = hdev->asic_specific; + + if (!(goya->hw_cap_initialized & HW_CAP_MME)) + goto disable_tpc; + WREG32(mmMME_QM_GLBL_CFG0, 0); WREG32(mmMME_CMDQ_GLBL_CFG0, 0); +disable_tpc: + if (!(goya->hw_cap_initialized & HW_CAP_TPC)) + return; + WREG32(mmTPC0_QM_GLBL_CFG0, 0); WREG32(mmTPC0_CMDQ_GLBL_CFG0, 0); @@ -1757,8 +1776,12 @@ static void goya_disable_internal_queues(struct hl_device *hdev) */ static int goya_stop_internal_queues(struct hl_device *hdev) { + struct goya_device *goya = hdev->asic_specific; int rc, retval = 0; + if (!(goya->hw_cap_initialized & HW_CAP_MME)) + goto stop_tpc; + /* * Each queue (QMAN) is a separate H/W logic. That means that each * QMAN can be stopped independently and failure to stop one does NOT @@ -1785,6 +1808,10 @@ static int goya_stop_internal_queues(struct hl_device *hdev) retval = -EIO; } +stop_tpc: + if (!(goya->hw_cap_initialized & HW_CAP_TPC)) + return retval; + rc = goya_stop_queue(hdev, mmTPC0_QM_GLBL_CFG1, mmTPC0_QM_CP_STS, @@ -1950,6 +1977,11 @@ static int goya_stop_internal_queues(struct hl_device *hdev) static void goya_dma_stall(struct hl_device *hdev) { + struct goya_device *goya = hdev->asic_specific; + + if (!(goya->hw_cap_initialized & HW_CAP_DMA)) + return; + WREG32(mmDMA_QM_0_GLBL_CFG1, 1 << DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT); WREG32(mmDMA_QM_1_GLBL_CFG1, 1 << DMA_QM_1_GLBL_CFG1_DMA_STOP_SHIFT); WREG32(mmDMA_QM_2_GLBL_CFG1, 1 << DMA_QM_2_GLBL_CFG1_DMA_STOP_SHIFT); @@ -1959,6 +1991,11 @@ static void goya_dma_stall(struct hl_device *hdev) static void goya_tpc_stall(struct hl_device *hdev) { + struct goya_device *goya = hdev->asic_specific; + + if (!(goya->hw_cap_initialized & HW_CAP_TPC)) + return; + WREG32(mmTPC0_CFG_TPC_STALL, 1 << TPC0_CFG_TPC_STALL_V_SHIFT); WREG32(mmTPC1_CFG_TPC_STALL, 1 << TPC1_CFG_TPC_STALL_V_SHIFT); WREG32(mmTPC2_CFG_TPC_STALL, 1 << TPC2_CFG_TPC_STALL_V_SHIFT); @@ -1971,6 +2008,11 @@ static void goya_tpc_stall(struct hl_device *hdev) static void goya_mme_stall(struct hl_device *hdev) { + struct goya_device *goya = hdev->asic_specific; + + if (!(goya->hw_cap_initialized & HW_CAP_MME)) + return; + WREG32(mmMME_STALL, 0xFFFFFFFF); } @@ -4624,8 +4666,6 @@ static int goya_memset_device_memory(struct hl_device *hdev, u64 addr, u64 size, rc = goya_send_job_on_qman0(hdev, job); - hl_cb_put(job->patched_cb); - hl_debugfs_remove_job(hdev, job); kfree(job); cb->cs_cnt--; diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c new file mode 100644 index 000000000000..32015bc9ccf6 --- /dev/null +++ b/drivers/misc/hisi_hikey_usb.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for usb functionality of Hikey series boards + * based on Hisilicon Kirin Soc. + * + * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd. + * http://www.huawei.com + * + * Authors: Yu Chen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_DRIVER_NAME "hisi_hikey_usb" + +#define HUB_VBUS_POWER_ON 1 +#define HUB_VBUS_POWER_OFF 0 +#define USB_SWITCH_TO_HUB 1 +#define USB_SWITCH_TO_TYPEC 0 +#define TYPEC_VBUS_POWER_ON 1 +#define TYPEC_VBUS_POWER_OFF 0 + +struct hisi_hikey_usb { + struct gpio_desc *otg_switch; + struct gpio_desc *typec_vbus; + struct gpio_desc *hub_vbus; + + struct usb_role_switch *hub_role_sw; + struct usb_role_switch *dev_role_sw; + struct notifier_block nb; +}; + +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value) +{ + gpiod_set_value_cansleep(hisi_hikey_usb->hub_vbus, value); +} + +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, + int switch_to) +{ + gpiod_set_value_cansleep(hisi_hikey_usb->otg_switch, switch_to); +} + +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, + int value) +{ + gpiod_set_value_cansleep(hisi_hikey_usb->typec_vbus, value); +} + +static int hub_usb_role_switch_set(struct device *dev, enum usb_role role) +{ + struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev); + + if (!hisi_hikey_usb || !hisi_hikey_usb->dev_role_sw) + return -EINVAL; + + switch (role) { + case USB_ROLE_NONE: + usb_typec_power_ctrl(hisi_hikey_usb, TYPEC_VBUS_POWER_OFF); + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB); + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON); + break; + case USB_ROLE_HOST: + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); + usb_typec_power_ctrl(hisi_hikey_usb, TYPEC_VBUS_POWER_ON); + break; + case USB_ROLE_DEVICE: + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); + usb_typec_power_ctrl(hisi_hikey_usb, TYPEC_VBUS_POWER_OFF); + usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC); + break; + default: + break; + } + + return usb_role_switch_set_role(hisi_hikey_usb->dev_role_sw, role); +} + +static enum usb_role hub_usb_role_switch_get(struct device *dev) +{ + struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev); + + if (!hisi_hikey_usb || !hisi_hikey_usb->dev_role_sw) + return -EINVAL; + + return usb_role_switch_get_role(hisi_hikey_usb->dev_role_sw); +} + +static int hisi_hikey_usb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct hisi_hikey_usb *hisi_hikey_usb; + struct usb_role_switch_desc hub_role_switch = {NULL}; + + hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL); + if (!hisi_hikey_usb) + return -ENOMEM; + + hisi_hikey_usb->typec_vbus = devm_gpiod_get(dev, "typec-vbus", + GPIOD_OUT_LOW); + if (IS_ERR(hisi_hikey_usb->typec_vbus)) + return PTR_ERR(hisi_hikey_usb->typec_vbus); + + hisi_hikey_usb->otg_switch = devm_gpiod_get(dev, "otg-switch", + GPIOD_OUT_HIGH); + if (IS_ERR(hisi_hikey_usb->otg_switch)) + return PTR_ERR(hisi_hikey_usb->otg_switch); + + /* hub-vdd33-en is optional */ + hisi_hikey_usb->hub_vbus = devm_gpiod_get_optional(dev, "hub-vdd33-en", + GPIOD_OUT_HIGH); + if (IS_ERR(hisi_hikey_usb->hub_vbus)) + return PTR_ERR(hisi_hikey_usb->hub_vbus); + + hisi_hikey_usb->dev_role_sw = usb_role_switch_get(dev); + if (!hisi_hikey_usb->dev_role_sw) + return -EPROBE_DEFER; + if (IS_ERR(hisi_hikey_usb->dev_role_sw)) + return PTR_ERR(hisi_hikey_usb->dev_role_sw); + + hub_role_switch.fwnode = dev_fwnode(dev); + hub_role_switch.set = hub_usb_role_switch_set; + hub_role_switch.get = hub_usb_role_switch_get; + hisi_hikey_usb->hub_role_sw = usb_role_switch_register(dev, + &hub_role_switch); + + if (IS_ERR(hisi_hikey_usb->hub_role_sw)) { + usb_role_switch_put(hisi_hikey_usb->dev_role_sw); + return PTR_ERR(hisi_hikey_usb->hub_role_sw); + } + + platform_set_drvdata(pdev, hisi_hikey_usb); + + return 0; +} + +static int hisi_hikey_usb_remove(struct platform_device *pdev) +{ + struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev); + + if (hisi_hikey_usb->hub_role_sw) + usb_role_switch_unregister(hisi_hikey_usb->hub_role_sw); + + if (hisi_hikey_usb->dev_role_sw) + usb_role_switch_put(hisi_hikey_usb->dev_role_sw); + + return 0; +} + +static const struct of_device_id id_table_hisi_hikey_usb[] = { + {.compatible = "hisilicon,gpio_hubv1"}, + {} +}; +MODULE_DEVICE_TABLE(of, id_table_hisi_hikey_usb); + +static struct platform_driver hisi_hikey_usb_driver = { + .probe = hisi_hikey_usb_probe, + .remove = hisi_hikey_usb_remove, + .driver = { + .name = DEVICE_DRIVER_NAME, + .of_match_table = id_table_hisi_hikey_usb, + }, +}; + +module_platform_driver(hisi_hikey_usb_driver); + +MODULE_AUTHOR("Yu Chen "); +MODULE_DESCRIPTION("Driver Support for USB functionality of Hikey"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c index 49974954d4f0..2e31a5611cb7 100644 --- a/drivers/misc/uid_sys_stats.c +++ b/drivers/misc/uid_sys_stats.c @@ -14,7 +14,6 @@ */ #include -#include #include #include #include @@ -424,9 +423,6 @@ static ssize_t uid_remove_write(struct file *file, return -EINVAL; } - /* Also remove uids from /proc/uid_time_in_state */ - cpufreq_task_times_remove_uids(uid_start, uid_end); - rt_mutex_lock(&uid_lock); for (; uid_start <= uid_end; uid_start++) { diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index cb6bedcba435..ba696d5bec1c 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2422,8 +2422,11 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, * the erase operation does not exceed the max_busy_timeout, we should * use R1B response. Or we need to prevent the host from doing hw busy * detection, which is done by converting to a R1 response instead. + * Note, some hosts requires R1B, which also means they are on their own + * when it comes to deal with the busy timeout. */ - if (card->host->max_busy_timeout && + if (!(card->host->caps & MMC_CAP_NEED_RSP_BUSY) && + card->host->max_busy_timeout && busy_timeout > card->host->max_busy_timeout) { cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; } else { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index c8804895595f..b7159e243323 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1911,9 +1911,12 @@ static int mmc_sleep(struct mmc_host *host) * If the max_busy_timeout of the host is specified, validate it against * the sleep cmd timeout. A failure means we need to prevent the host * from doing hw busy detection, which is done by converting to a R1 - * response instead of a R1B. + * response instead of a R1B. Note, some hosts requires R1B, which also + * means they are on their own when it comes to deal with the busy + * timeout. */ - if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) { + if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout && + (timeout_ms > host->max_busy_timeout)) { cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; } else { cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 09113b9ad679..18a7afb2a5b2 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -538,10 +538,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, * If the cmd timeout and the max_busy_timeout of the host are both * specified, let's validate them. A failure means we need to prevent * the host from doing hw busy detection, which is done by converting - * to a R1 response instead of a R1B. + * to a R1 response instead of a R1B. Note, some hosts requires R1B, + * which also means they are on their own when it comes to deal with the + * busy timeout. */ - if (timeout_ms && host->max_busy_timeout && - (timeout_ms > host->max_busy_timeout)) + if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && timeout_ms && + host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) use_r1b_resp = false; cmd.opcode = MMC_SWITCH; diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index bd50935dc37d..11087976ab19 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -606,19 +606,22 @@ static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point, bool rx) { struct rtsx_pcr *pcr = host->pcr; - + u16 SD_VP_CTL = 0; dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n", __func__, rx ? "RX" : "TX", sample_point); rtsx_pci_write_register(pcr, CLK_CTL, CHANGE_CLK, CHANGE_CLK); - if (rx) + if (rx) { + SD_VP_CTL = SD_VPRX_CTL; rtsx_pci_write_register(pcr, SD_VPRX_CTL, PHASE_SELECT_MASK, sample_point); - else + } else { + SD_VP_CTL = SD_VPTX_CTL; rtsx_pci_write_register(pcr, SD_VPTX_CTL, PHASE_SELECT_MASK, sample_point); - rtsx_pci_write_register(pcr, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); - rtsx_pci_write_register(pcr, SD_VPCLK0_CTL, PHASE_NOT_RESET, + } + rtsx_pci_write_register(pcr, SD_VP_CTL, PHASE_NOT_RESET, 0); + rtsx_pci_write_register(pcr, SD_VP_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET); rtsx_pci_write_register(pcr, CLK_CTL, CHANGE_CLK, 0); rtsx_pci_write_register(pcr, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0); diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index ae0ec27dd7cc..5f2e9696ee4d 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "sdhci-pltfm.h" @@ -235,6 +236,11 @@ static const struct sdhci_ops sdhci_cdns_ops = { .set_uhs_signaling = sdhci_cdns_set_uhs_signaling, }; +static const struct sdhci_pltfm_data sdhci_cdns_uniphier_pltfm_data = { + .ops = &sdhci_cdns_ops, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, +}; + static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = { .ops = &sdhci_cdns_ops, }; @@ -334,6 +340,7 @@ static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc, static int sdhci_cdns_probe(struct platform_device *pdev) { struct sdhci_host *host; + const struct sdhci_pltfm_data *data; struct sdhci_pltfm_host *pltfm_host; struct sdhci_cdns_priv *priv; struct clk *clk; @@ -350,8 +357,12 @@ static int sdhci_cdns_probe(struct platform_device *pdev) if (ret) return ret; + data = of_device_get_match_data(dev); + if (!data) + data = &sdhci_cdns_pltfm_data; + nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node); - host = sdhci_pltfm_init(pdev, &sdhci_cdns_pltfm_data, + host = sdhci_pltfm_init(pdev, data, struct_size(priv, phy_params, nr_phy_params)); if (IS_ERR(host)) { ret = PTR_ERR(host); @@ -431,7 +442,10 @@ static const struct dev_pm_ops sdhci_cdns_pm_ops = { }; static const struct of_device_id sdhci_cdns_match[] = { - { .compatible = "socionext,uniphier-sd4hc" }, + { + .compatible = "socionext,uniphier-sd4hc", + .data = &sdhci_cdns_uniphier_pltfm_data, + }, { .compatible = "cdns,sd4hc" }, { /* sentinel */ } }; diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index 9378d5dc86c8..881f8138e7de 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -118,7 +118,8 @@ static void sdhci_at91_reset(struct sdhci_host *host, u8 mask) { sdhci_reset(host, mask); - if (host->mmc->caps & MMC_CAP_NONREMOVABLE) + if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) + || mmc_gpio_get_cd(host->mmc) >= 0) sdhci_at91_set_force_card_detect(host); } @@ -397,8 +398,11 @@ static int sdhci_at91_probe(struct platform_device *pdev) * detection procedure using the SDMCC_CD signal is bypassed. * This bit is reset when a software reset for all command is performed * so we need to implement our own reset function to set back this bit. + * + * WA: SAMA5D2 doesn't drive CMD if using CD GPIO line. */ - if (host->mmc->caps & MMC_CAP_NONREMOVABLE) + if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) + || mmc_gpio_get_cd(host->mmc) >= 0) sdhci_at91_set_force_card_detect(host); pm_runtime_put_autosuspend(&pdev->dev); diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 083e7e053c95..d3135249b2e4 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -1134,6 +1134,9 @@ static int sdhci_omap_probe(struct platform_device *pdev) host->mmc_host_ops.execute_tuning = sdhci_omap_execute_tuning; host->mmc_host_ops.enable_sdio_irq = sdhci_omap_enable_sdio_irq; + /* R1B responses is required to properly manage HW busy detection. */ + mmc->caps |= MMC_CAP_NEED_RSP_BUSY; + ret = sdhci_setup_host(host); if (ret) goto err_put_sync; diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 5eea8d70a85d..ce15a05f23d4 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -262,10 +262,26 @@ static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode) return 0; } +static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot) +{ + int ret; + + ret = pci_alloc_irq_vectors(slot->chip->pdev, 1, 1, + PCI_IRQ_MSI | PCI_IRQ_MSIX); + if (ret < 0) { + pr_warn("%s: enable PCI MSI failed, error=%d\n", + mmc_hostname(slot->host->mmc), ret); + return; + } + + slot->host->irq = pci_irq_vector(slot->chip->pdev, 0); +} + static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) { struct sdhci_host *host = slot->host; + gli_pcie_enable_msi(slot); slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; sdhci_enable_v4_mode(host); @@ -276,6 +292,7 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) { struct sdhci_host *host = slot->host; + gli_pcie_enable_msi(slot); slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; sdhci_enable_v4_mode(host); diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 403ac44a7378..a25c3a4d3f6c 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -1552,6 +1552,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev) if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) host->mmc->caps |= MMC_CAP_1_8V_DDR; + /* R1B responses is required to properly manage HW busy detection. */ + host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY; + tegra_sdhci_parse_dt(host); tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index df1c7989e13d..df3cd2589bcf 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -106,6 +106,7 @@ config NET_FC config IFB tristate "Intermediate Functional Block support" depends on NET_CLS_ACT + select NET_REDIRECT ---help--- This is an intermediate driver that allows sharing of resources. diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 1cc2cd894f87..c81698550e5a 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -50,11 +50,6 @@ struct arp_pkt { }; #pragma pack() -static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb) -{ - return (struct arp_pkt *)skb_network_header(skb); -} - /* Forward declaration */ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[], bool strict_match); @@ -553,10 +548,11 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip) spin_unlock(&bond->mode_lock); } -static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond) +static struct slave *rlb_choose_channel(struct sk_buff *skb, + struct bonding *bond, + const struct arp_pkt *arp) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - struct arp_pkt *arp = arp_pkt(skb); struct slave *assigned_slave, *curr_active_slave; struct rlb_client_info *client_info; u32 hash_index = 0; @@ -653,8 +649,12 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon */ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) { - struct arp_pkt *arp = arp_pkt(skb); struct slave *tx_slave = NULL; + struct arp_pkt *arp; + + if (!pskb_network_may_pull(skb, sizeof(*arp))) + return NULL; + arp = (struct arp_pkt *)skb_network_header(skb); /* Don't modify or load balance ARPs that do not originate locally * (e.g.,arrive via a bridge). @@ -664,7 +664,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) if (arp->op_code == htons(ARPOP_REPLY)) { /* the arp must be sent on the selected rx channel */ - tx_slave = rlb_choose_channel(skb, bond); + tx_slave = rlb_choose_channel(skb, bond, arp); if (tx_slave) bond_hw_addr_copy(arp->mac_src, tx_slave->dev->dev_addr, tx_slave->dev->addr_len); @@ -676,7 +676,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) * When the arp reply is received the entry will be updated * with the correct unicast address of the client. */ - tx_slave = rlb_choose_channel(skb, bond); + tx_slave = rlb_choose_channel(skb, bond, arp); /* The ARP reply packets must be delayed so that * they can cancel out the influence of the ARP request. diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 1c88c361938c..3a33fb503400 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -884,6 +884,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { = { .len = sizeof(struct can_bittiming) }, [IFLA_CAN_DATA_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, + [IFLA_CAN_TERMINATION] = { .type = NLA_U16 }, }; static int can_validate(struct nlattr *tb[], struct nlattr *data[], diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 2f5c287eac95..a3664281a33f 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -625,7 +625,10 @@ err_free_chan: tty->disc_data = NULL; clear_bit(SLF_INUSE, &sl->flags); slc_free_netdev(sl->dev); + /* do not call free_netdev before rtnl_unlock */ + rtnl_unlock(); free_netdev(sl->dev); + return err; err_exit: rtnl_unlock(); diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index fecd5e674e04..46dc913da852 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -69,8 +69,7 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) /* Force link status for IMP port */ reg = core_readl(priv, offset); reg |= (MII_SW_OR | LINK_STS); - if (priv->type == BCM7278_DEVICE_ID) - reg |= GMII_SPEED_UP_2G; + reg &= ~GMII_SPEED_UP_2G; core_writel(priv, reg, offset); /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */ diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 1d8d36de4d20..e0e932f0aed1 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -566,7 +566,7 @@ mt7530_mib_reset(struct dsa_switch *ds) static void mt7530_port_set_status(struct mt7530_priv *priv, int port, int enable) { - u32 mask = PMCR_TX_EN | PMCR_RX_EN; + u32 mask = PMCR_TX_EN | PMCR_RX_EN | PMCR_FORCE_LNK; if (enable) mt7530_set(priv, MT7530_PMCR_P(port), mask); @@ -1439,7 +1439,7 @@ static void mt7530_phylink_mac_config(struct dsa_switch *ds, int port, mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 | PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN); mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN | - PMCR_BACKPR_EN | PMCR_FORCE_MODE | PMCR_FORCE_LNK; + PMCR_BACKPR_EN | PMCR_FORCE_MODE; /* Are we connected to external phy */ if (port == 5 && dsa_is_user_port(ds, 5)) diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index bdbb72fc20ed..6240976679e1 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -1083,6 +1083,13 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) { int err, irq, virq; + chip->g2_irq.masked = ~0; + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_g2_int_mask(chip, ~chip->g2_irq.masked); + mv88e6xxx_reg_unlock(chip); + if (err) + return err; + chip->g2_irq.domain = irq_domain_add_simple( chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip); if (!chip->g2_irq.domain) @@ -1092,7 +1099,6 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) irq_create_mapping(chip->g2_irq.domain, irq); chip->g2_irq.chip = mv88e6xxx_g2_irq_chip; - chip->g2_irq.masked = ~0; chip->device_irq = irq_find_mapping(chip->g1_irq.domain, MV88E6XXX_G1_STS_IRQ_DEVICE); diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index f0cddf250cfd..26325f7b3c1f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -3652,13 +3652,15 @@ err_disable_device: /*****************************************************************************/ -/* ena_remove - Device Removal Routine +/* __ena_shutoff - Helper used in both PCI remove/shutdown routines * @pdev: PCI device information struct + * @shutdown: Is it a shutdown operation? If false, means it is a removal * - * ena_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. + * __ena_shutoff is a helper routine that does the real work on shutdown and + * removal paths; the difference between those paths is with regards to whether + * dettach or unregister the netdevice. */ -static void ena_remove(struct pci_dev *pdev) +static void __ena_shutoff(struct pci_dev *pdev, bool shutdown) { struct ena_adapter *adapter = pci_get_drvdata(pdev); struct ena_com_dev *ena_dev; @@ -3677,13 +3679,17 @@ static void ena_remove(struct pci_dev *pdev) cancel_work_sync(&adapter->reset_task); - rtnl_lock(); + rtnl_lock(); /* lock released inside the below if-else block */ ena_destroy_device(adapter, true); - rtnl_unlock(); - - unregister_netdev(netdev); - - free_netdev(netdev); + if (shutdown) { + netif_device_detach(netdev); + dev_close(netdev); + rtnl_unlock(); + } else { + rtnl_unlock(); + unregister_netdev(netdev); + free_netdev(netdev); + } ena_com_rss_destroy(ena_dev); @@ -3698,6 +3704,30 @@ static void ena_remove(struct pci_dev *pdev) vfree(ena_dev); } +/* ena_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * ena_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. + */ + +static void ena_remove(struct pci_dev *pdev) +{ + __ena_shutoff(pdev, false); +} + +/* ena_shutdown - Device Shutdown Routine + * @pdev: PCI device information struct + * + * ena_shutdown is called by the PCI subsystem to alert the driver that + * a shutdown/reboot (or kexec) is happening and device must be disabled. + */ + +static void ena_shutdown(struct pci_dev *pdev) +{ + __ena_shutoff(pdev, true); +} + #ifdef CONFIG_PM /* ena_suspend - PM suspend callback * @pdev: PCI device information struct @@ -3747,6 +3777,7 @@ static struct pci_driver ena_pci_driver = { .id_table = ena_pci_tbl, .probe = ena_probe, .remove = ena_remove, + .shutdown = ena_shutdown, #ifdef CONFIG_PM .suspend = ena_suspend, .resume = ena_resume, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index 52646855495e..873f9865f0d1 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -22,6 +22,7 @@ #define HW_ATL_MIF_ADDR 0x0208U #define HW_ATL_MIF_VAL 0x020CU +#define HW_ATL_MPI_RPC_ADDR 0x0334U #define HW_ATL_RPC_CONTROL_ADR 0x0338U #define HW_ATL_RPC_STATE_ADR 0x033CU @@ -48,15 +49,14 @@ #define FORCE_FLASHLESS 0 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); - static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, enum hal_atl_utils_fw_state_e state); - static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self); static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self); static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self); static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self); static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self); +static u32 aq_fw1x_rpc_get(struct aq_hw_s *self); int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) { @@ -413,6 +413,10 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self, self, self->mbox_addr, self->mbox_addr != 0U, 1000U, 10000U); + err = readx_poll_timeout_atomic(aq_fw1x_rpc_get, self, + self->rpc_addr, + self->rpc_addr != 0U, + 1000U, 100000U); return err; } @@ -469,6 +473,12 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, self, fw.val, sw.tid == fw.tid, 1000U, 100000U); + if (err < 0) + goto err_exit; + + err = aq_hw_err_from_flags(self); + if (err < 0) + goto err_exit; if (fw.len == 0xFFFFU) { err = hw_atl_utils_fw_rpc_call(self, sw.len); @@ -950,6 +960,11 @@ static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self) return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR); } +static u32 aq_fw1x_rpc_get(struct aq_hw_s *self) +{ + return aq_hw_read_reg(self, HW_ATL_MPI_RPC_ADDR); +} + const struct aq_fw_ops aq_fw_1x_ops = { .init = hw_atl_utils_mpi_create, .deinit = hw_atl_fw1x_deinit, diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 4a27577e137b..ad86a186ddc5 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -2135,7 +2135,7 @@ static int bcm_sysport_rule_set(struct bcm_sysport_priv *priv, return -ENOSPC; index = find_first_zero_bit(priv->filters, RXCHK_BRCM_TAG_MAX); - if (index > RXCHK_BRCM_TAG_MAX) + if (index >= RXCHK_BRCM_TAG_MAX) return -ENOSPC; /* Location is the classification ID, and index is the position diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 374e11a91790..6862594b49ab 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6863,12 +6863,12 @@ skip_rdma: } ena |= FUNC_BACKING_STORE_CFG_REQ_DFLT_ENABLES; rc = bnxt_hwrm_func_backing_store_cfg(bp, ena); - if (rc) + if (rc) { netdev_err(bp->dev, "Failed configuring context mem, rc = %d.\n", rc); - else - ctx->flags |= BNXT_CTX_FLAG_INITED; - + return rc; + } + ctx->flags |= BNXT_CTX_FLAG_INITED; return 0; } @@ -7387,14 +7387,22 @@ static int bnxt_hwrm_port_qstats_ext(struct bnxt *bp) pri2cos = &resp2->pri0_cos_queue_id; for (i = 0; i < 8; i++) { u8 queue_id = pri2cos[i]; + u8 queue_idx; + /* Per port queue IDs start from 0, 10, 20, etc */ + queue_idx = queue_id % 10; + if (queue_idx > BNXT_MAX_QUEUE) { + bp->pri2cos_valid = false; + goto qstats_done; + } for (j = 0; j < bp->max_q; j++) { if (bp->q_ids[j] == queue_id) - bp->pri2cos[i] = j; + bp->pri2cos_idx[i] = queue_idx; } } bp->pri2cos_valid = 1; } +qstats_done: mutex_unlock(&bp->hwrm_cmd_lock); return rc; } @@ -10891,13 +10899,13 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu) struct bnxt *bp = netdev_priv(dev); if (netif_running(dev)) - bnxt_close_nic(bp, false, false); + bnxt_close_nic(bp, true, false); dev->mtu = new_mtu; bnxt_set_ring_params(bp); if (netif_running(dev)) - return bnxt_open_nic(bp, false, false); + return bnxt_open_nic(bp, true, false); return 0; } @@ -11595,6 +11603,10 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) bp->rx_nr_rings++; bp->cp_nr_rings++; } + if (rc) { + bp->tx_nr_rings = 0; + bp->rx_nr_rings = 0; + } return rc; } @@ -11887,12 +11899,12 @@ init_err_cleanup: init_err_pci_clean: bnxt_free_hwrm_short_cmd_req(bp); bnxt_free_hwrm_resources(bp); - bnxt_free_ctx_mem(bp); - kfree(bp->ctx); - bp->ctx = NULL; kfree(bp->fw_health); bp->fw_health = NULL; bnxt_cleanup_pci(bp); + bnxt_free_ctx_mem(bp); + kfree(bp->ctx); + bp->ctx = NULL; init_err_free: free_netdev(dev); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 2e6ad53fdc75..cda7ba31095a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1688,7 +1688,7 @@ struct bnxt { u16 fw_rx_stats_ext_size; u16 fw_tx_stats_ext_size; u16 hw_ring_stats_size; - u8 pri2cos[8]; + u8 pri2cos_idx[8]; u8 pri2cos_valid; u16 hwrm_max_req_len; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c index fb6f30d0d1d0..b1511bcffb1b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c @@ -479,24 +479,26 @@ static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) { struct bnxt *bp = netdev_priv(dev); struct ieee_ets *my_ets = bp->ieee_ets; + int rc; ets->ets_cap = bp->max_tc; if (!my_ets) { - int rc; - if (bp->dcbx_cap & DCB_CAP_DCBX_HOST) return 0; my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL); if (!my_ets) - return 0; + return -ENOMEM; rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets); if (rc) - return 0; + goto error; rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets); if (rc) - return 0; + goto error; + + /* cache result */ + bp->ieee_ets = my_ets; } ets->cbs = my_ets->cbs; @@ -505,6 +507,9 @@ static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); return 0; +error: + kfree(my_ets); + return rc; } static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index ece70f61c89a..fb1ab58da9fa 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -589,25 +589,25 @@ skip_ring_stats: if (bp->pri2cos_valid) { for (i = 0; i < 8; i++, j++) { long n = bnxt_rx_bytes_pri_arr[i].base_off + - bp->pri2cos[i]; + bp->pri2cos_idx[i]; buf[j] = le64_to_cpu(*(rx_port_stats_ext + n)); } for (i = 0; i < 8; i++, j++) { long n = bnxt_rx_pkts_pri_arr[i].base_off + - bp->pri2cos[i]; + bp->pri2cos_idx[i]; buf[j] = le64_to_cpu(*(rx_port_stats_ext + n)); } for (i = 0; i < 8; i++, j++) { long n = bnxt_tx_bytes_pri_arr[i].base_off + - bp->pri2cos[i]; + bp->pri2cos_idx[i]; buf[j] = le64_to_cpu(*(tx_port_stats_ext + n)); } for (i = 0; i < 8; i++, j++) { long n = bnxt_tx_pkts_pri_arr[i].base_off + - bp->pri2cos[i]; + bp->pri2cos_idx[i]; buf[j] = le64_to_cpu(*(tx_port_stats_ext + n)); } @@ -2005,8 +2005,8 @@ static int bnxt_flash_package_from_file(struct net_device *dev, struct hwrm_nvm_install_update_output *resp = bp->hwrm_cmd_resp_addr; struct hwrm_nvm_install_update_input install = {0}; const struct firmware *fw; - int rc, hwrm_err = 0; u32 item_len; + int rc = 0; u16 index; bnxt_hwrm_fw_set_time(bp); @@ -2050,15 +2050,14 @@ static int bnxt_flash_package_from_file(struct net_device *dev, memcpy(kmem, fw->data, fw->size); modify.host_src_addr = cpu_to_le64(dma_handle); - hwrm_err = hwrm_send_message(bp, &modify, - sizeof(modify), - FLASH_PACKAGE_TIMEOUT); + rc = hwrm_send_message(bp, &modify, sizeof(modify), + FLASH_PACKAGE_TIMEOUT); dma_free_coherent(&bp->pdev->dev, fw->size, kmem, dma_handle); } } release_firmware(fw); - if (rc || hwrm_err) + if (rc) goto err_exit; if ((install_type & 0xffff) == 0) @@ -2067,20 +2066,19 @@ static int bnxt_flash_package_from_file(struct net_device *dev, install.install_type = cpu_to_le32(install_type); mutex_lock(&bp->hwrm_cmd_lock); - hwrm_err = _hwrm_send_message(bp, &install, sizeof(install), - INSTALL_PACKAGE_TIMEOUT); - if (hwrm_err) { + rc = _hwrm_send_message(bp, &install, sizeof(install), + INSTALL_PACKAGE_TIMEOUT); + if (rc) { u8 error_code = ((struct hwrm_err_output *)resp)->cmd_err; if (resp->error_code && error_code == NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) { install.flags |= cpu_to_le16( NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG); - hwrm_err = _hwrm_send_message(bp, &install, - sizeof(install), - INSTALL_PACKAGE_TIMEOUT); + rc = _hwrm_send_message(bp, &install, sizeof(install), + INSTALL_PACKAGE_TIMEOUT); } - if (hwrm_err) + if (rc) goto flash_pkg_exit; } @@ -2092,7 +2090,7 @@ static int bnxt_flash_package_from_file(struct net_device *dev, flash_pkg_exit: mutex_unlock(&bp->hwrm_cmd_lock); err_exit: - if (hwrm_err == -EACCES) + if (rc == -EACCES) bnxt_print_admin_err(bp); return rc; } diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 6cc100e7d5c0..76ff42ec3ae5 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -410,10 +410,19 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable) lmac = &bgx->lmac[lmacid]; cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG); - if (enable) + if (enable) { cfg |= CMR_PKT_RX_EN | CMR_PKT_TX_EN; - else + + /* enable TX FIFO Underflow interrupt */ + bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_INT_ENA_W1S, + GMI_TXX_INT_UNDFLW); + } else { cfg &= ~(CMR_PKT_RX_EN | CMR_PKT_TX_EN); + + /* Disable TX FIFO Underflow interrupt */ + bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_INT_ENA_W1C, + GMI_TXX_INT_UNDFLW); + } bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg); if (bgx->is_rgx) @@ -1535,6 +1544,48 @@ static int bgx_init_phy(struct bgx *bgx) return bgx_init_of_phy(bgx); } +static irqreturn_t bgx_intr_handler(int irq, void *data) +{ + struct bgx *bgx = (struct bgx *)data; + u64 status, val; + int lmac; + + for (lmac = 0; lmac < bgx->lmac_count; lmac++) { + status = bgx_reg_read(bgx, lmac, BGX_GMP_GMI_TXX_INT); + if (status & GMI_TXX_INT_UNDFLW) { + pci_err(bgx->pdev, "BGX%d lmac%d UNDFLW\n", + bgx->bgx_id, lmac); + val = bgx_reg_read(bgx, lmac, BGX_CMRX_CFG); + val &= ~CMR_EN; + bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val); + val |= CMR_EN; + bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val); + } + /* clear interrupts */ + bgx_reg_write(bgx, lmac, BGX_GMP_GMI_TXX_INT, status); + } + + return IRQ_HANDLED; +} + +static void bgx_register_intr(struct pci_dev *pdev) +{ + struct bgx *bgx = pci_get_drvdata(pdev); + int ret; + + ret = pci_alloc_irq_vectors(pdev, BGX_LMAC_VEC_OFFSET, + BGX_LMAC_VEC_OFFSET, PCI_IRQ_ALL_TYPES); + if (ret < 0) { + pci_err(pdev, "Req for #%d msix vectors failed\n", + BGX_LMAC_VEC_OFFSET); + return; + } + ret = pci_request_irq(pdev, GMPX_GMI_TX_INT, bgx_intr_handler, NULL, + bgx, "BGX%d", bgx->bgx_id); + if (ret) + pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx); +} + static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err; @@ -1550,7 +1601,7 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, bgx); - err = pci_enable_device(pdev); + err = pcim_enable_device(pdev); if (err) { dev_err(dev, "Failed to enable PCI device\n"); pci_set_drvdata(pdev, NULL); @@ -1604,6 +1655,8 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) bgx_init_hw(bgx); + bgx_register_intr(pdev); + /* Enable all LMACs */ for (lmac = 0; lmac < bgx->lmac_count; lmac++) { err = bgx_lmac_enable(bgx, lmac); @@ -1620,6 +1673,7 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_enable: bgx_vnic[bgx->bgx_id] = NULL; + pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx); err_release_regions: pci_release_regions(pdev); err_disable_device: @@ -1637,6 +1691,8 @@ static void bgx_remove(struct pci_dev *pdev) for (lmac = 0; lmac < bgx->lmac_count; lmac++) bgx_lmac_disable(bgx, lmac); + pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx); + bgx_vnic[bgx->bgx_id] = NULL; pci_release_regions(pdev); pci_disable_device(pdev); diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h index 25888706bdcd..cdea49392185 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h @@ -180,6 +180,15 @@ #define BGX_GMP_GMI_TXX_BURST 0x38228 #define BGX_GMP_GMI_TXX_MIN_PKT 0x38240 #define BGX_GMP_GMI_TXX_SGMII_CTL 0x38300 +#define BGX_GMP_GMI_TXX_INT 0x38500 +#define BGX_GMP_GMI_TXX_INT_W1S 0x38508 +#define BGX_GMP_GMI_TXX_INT_ENA_W1C 0x38510 +#define BGX_GMP_GMI_TXX_INT_ENA_W1S 0x38518 +#define GMI_TXX_INT_PTP_LOST BIT_ULL(4) +#define GMI_TXX_INT_LATE_COL BIT_ULL(3) +#define GMI_TXX_INT_XSDEF BIT_ULL(2) +#define GMI_TXX_INT_XSCOL BIT_ULL(1) +#define GMI_TXX_INT_UNDFLW BIT_ULL(0) #define BGX_MSIX_VEC_0_29_ADDR 0x400000 /* +(0..29) << 4 */ #define BGX_MSIX_VEC_0_29_CTL 0x400008 diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 928bfea5457b..3a45ac8f0e01 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -1324,8 +1324,9 @@ static inline void t6_fill_tnl_lso(struct sk_buff *skb, int t4_sge_eth_txq_egress_update(struct adapter *adap, struct sge_eth_txq *eq, int maxreclaim) { + unsigned int reclaimed, hw_cidx; struct sge_txq *q = &eq->q; - unsigned int reclaimed; + int hw_in_use; if (!q->in_use || !__netif_tx_trylock(eq->txq)) return 0; @@ -1333,12 +1334,17 @@ int t4_sge_eth_txq_egress_update(struct adapter *adap, struct sge_eth_txq *eq, /* Reclaim pending completed TX Descriptors. */ reclaimed = reclaim_completed_tx(adap, &eq->q, maxreclaim, true); + hw_cidx = ntohs(READ_ONCE(q->stat->cidx)); + hw_in_use = q->pidx - hw_cidx; + if (hw_in_use < 0) + hw_in_use += q->size; + /* If the TX Queue is currently stopped and there's now more than half * the queue available, restart it. Otherwise bail out since the rest * of what we want do here is with the possibility of shipping any * currently buffered Coalesced TX Work Request. */ - if (netif_tx_queue_stopped(eq->txq) && txq_avail(q) > (q->size / 2)) { + if (netif_tx_queue_stopped(eq->txq) && hw_in_use < (q->size / 2)) { netif_tx_wake_queue(eq->txq); eq->q.restarts++; } @@ -1469,16 +1475,7 @@ out_free: dev_kfree_skb_any(skb); * has opened up. */ eth_txq_stop(q); - - /* If we're using the SGE Doorbell Queue Timer facility, we - * don't need to ask the Firmware to send us Egress Queue CIDX - * Updates: the Hardware will do this automatically. And - * since we send the Ingress Queue CIDX Updates to the - * corresponding Ethernet Response Queue, we'll get them very - * quickly. - */ - if (!q->dbqt) - wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; + wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; } wr = (void *)&q->q.desc[q->q.pidx]; @@ -1792,16 +1789,7 @@ static netdev_tx_t cxgb4_vf_eth_xmit(struct sk_buff *skb, * has opened up. */ eth_txq_stop(txq); - - /* If we're using the SGE Doorbell Queue Timer facility, we - * don't need to ask the Firmware to send us Egress Queue CIDX - * Updates: the Hardware will do this automatically. And - * since we send the Ingress Queue CIDX Updates to the - * corresponding Ethernet Response Queue, we'll get them very - * quickly. - */ - if (!txq->dbqt) - wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; + wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; } /* Start filling in our Work Request. Note that we do _not_ handle @@ -2924,26 +2912,6 @@ static void t4_tx_completion_handler(struct sge_rspq *rspq, } txq = &s->ethtxq[pi->first_qset + rspq->idx]; - - /* We've got the Hardware Consumer Index Update in the Egress Update - * message. If we're using the SGE Doorbell Queue Timer mechanism, - * these Egress Update messages will be our sole CIDX Updates we get - * since we don't want to chew up PCIe bandwidth for both Ingress - * Messages and Status Page writes. However, The code which manages - * reclaiming successfully DMA'ed TX Work Requests uses the CIDX value - * stored in the Status Page at the end of the TX Queue. It's easiest - * to simply copy the CIDX Update value from the Egress Update message - * to the Status Page. Also note that no Endian issues need to be - * considered here since both are Big Endian and we're just copying - * bytes consistently ... - */ - if (txq->dbqt) { - struct cpl_sge_egr_update *egr; - - egr = (struct cpl_sge_egr_update *)rsp; - WRITE_ONCE(txq->q.stat->cidx, egr->cidx); - } - t4_sge_eth_txq_egress_update(adapter, txq, -1); } diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index cce90b5925d9..70060c51854f 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1405,6 +1405,8 @@ static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev) mac_addr = of_get_mac_address(np); if (!IS_ERR(mac_addr)) ether_addr_copy(pdata->dev_addr, mac_addr); + else if (PTR_ERR(mac_addr) == -EPROBE_DEFER) + return ERR_CAST(mac_addr); return pdata; } diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index e130233b5085..00c4beb760c3 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -2770,9 +2770,7 @@ static inline u16 dpaa_get_headroom(struct dpaa_buffer_layout *bl) headroom = (u16)(bl->priv_data_size + DPAA_PARSE_RESULTS_SIZE + DPAA_TIME_STAMP_SIZE + DPAA_HASH_RESULTS_SIZE); - return DPAA_FD_DATA_ALIGNMENT ? ALIGN(headroom, - DPAA_FD_DATA_ALIGNMENT) : - headroom; + return ALIGN(headroom, DPAA_FD_DATA_ALIGNMENT); } static int dpaa_eth_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 8336f4cbaf95..3fc8a66e4f41 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2529,15 +2529,15 @@ fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec) return -EINVAL; } - cycle = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr); + cycle = fec_enet_us_to_itr_clock(ndev, ec->rx_coalesce_usecs); if (cycle > 0xFFFF) { dev_err(dev, "Rx coalesced usec exceed hardware limitation\n"); return -EINVAL; } - cycle = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr); + cycle = fec_enet_us_to_itr_clock(ndev, ec->tx_coalesce_usecs); if (cycle > 0xFFFF) { - dev_err(dev, "Rx coalesced usec exceed hardware limitation\n"); + dev_err(dev, "Tx coalesced usec exceed hardware limitation\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig index 0139cb9042ec..34150182cc35 100644 --- a/drivers/net/ethernet/freescale/fman/Kconfig +++ b/drivers/net/ethernet/freescale/fman/Kconfig @@ -8,3 +8,31 @@ config FSL_FMAN help Freescale Data-Path Acceleration Architecture Frame Manager (FMan) support + +config DPAA_ERRATUM_A050385 + bool + depends on ARM64 && FSL_DPAA + default y + help + DPAA FMan erratum A050385 software workaround implementation: + align buffers, data start, SG fragment length to avoid FMan DMA + splits. + FMAN DMA read or writes under heavy traffic load may cause FMAN + internal resource leak thus stopping further packet processing. + The FMAN internal queue can overflow when FMAN splits single + read or write transactions into multiple smaller transactions + such that more than 17 AXI transactions are in flight from FMAN + to interconnect. When the FMAN internal queue overflows, it can + stall further packet processing. The issue can occur with any + one of the following three conditions: + 1. FMAN AXI transaction crosses 4K address boundary (Errata + A010022) + 2. FMAN DMA address for an AXI transaction is not 16 byte + aligned, i.e. the last 4 bits of an address are non-zero + 3. Scatter Gather (SG) frames have more than one SG buffer in + the SG list and any one of the buffers, except the last + buffer in the SG list has data size that is not a multiple + of 16 bytes, i.e., other than 16, 32, 48, 64, etc. + With any one of the above three conditions present, there is + likelihood of stalled FMAN packet processing, especially under + stress with multiple ports injecting line-rate traffic. diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c index 210749bf1eac..4c2fa13a7dd7 100644 --- a/drivers/net/ethernet/freescale/fman/fman.c +++ b/drivers/net/ethernet/freescale/fman/fman.c @@ -1,5 +1,6 @@ /* * Copyright 2008-2015 Freescale Semiconductor Inc. + * Copyright 2020 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -566,6 +567,10 @@ struct fman_cfg { u32 qmi_def_tnums_thresh; }; +#ifdef CONFIG_DPAA_ERRATUM_A050385 +static bool fman_has_err_a050385; +#endif + static irqreturn_t fman_exceptions(struct fman *fman, enum fman_exceptions exception) { @@ -2514,6 +2519,14 @@ struct fman *fman_bind(struct device *fm_dev) } EXPORT_SYMBOL(fman_bind); +#ifdef CONFIG_DPAA_ERRATUM_A050385 +bool fman_has_errata_a050385(void) +{ + return fman_has_err_a050385; +} +EXPORT_SYMBOL(fman_has_errata_a050385); +#endif + static irqreturn_t fman_err_irq(int irq, void *handle) { struct fman *fman = (struct fman *)handle; @@ -2841,6 +2854,11 @@ static struct fman *read_dts_node(struct platform_device *of_dev) goto fman_free; } +#ifdef CONFIG_DPAA_ERRATUM_A050385 + fman_has_err_a050385 = + of_property_read_bool(fm_node, "fsl,erratum-a050385"); +#endif + return fman; fman_node_put: diff --git a/drivers/net/ethernet/freescale/fman/fman.h b/drivers/net/ethernet/freescale/fman/fman.h index 935c317fa696..f2ede1360f03 100644 --- a/drivers/net/ethernet/freescale/fman/fman.h +++ b/drivers/net/ethernet/freescale/fman/fman.h @@ -1,5 +1,6 @@ /* * Copyright 2008-2015 Freescale Semiconductor Inc. + * Copyright 2020 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -398,6 +399,10 @@ u16 fman_get_max_frm(void); int fman_get_rx_extra_headroom(void); +#ifdef CONFIG_DPAA_ERRATUM_A050385 +bool fman_has_errata_a050385(void); +#endif + struct fman *fman_bind(struct device *dev); #endif /* __FM_H */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0c8d2269bc46..403e0f089f2a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1596,7 +1596,7 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) netif_dbg(h, drv, netdev, "setup tc: num_tc=%u\n", tc); return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ? - kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP; + kinfo->dcb_ops->setup_tc(h, tc ? tc : 1, prio_tc) : -EOPNOTSUPP; } static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index c01cf8ef69df..d4652dea4569 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2417,10 +2417,12 @@ static int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed, int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex) { + struct hclge_mac *mac = &hdev->hw.mac; int ret; duplex = hclge_check_speed_dup(duplex, speed); - if (hdev->hw.mac.speed == speed && hdev->hw.mac.duplex == duplex) + if (!mac->support_autoneg && mac->speed == speed && + mac->duplex == duplex) return 0; ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 6f2cf569a283..79b3d53f2fbf 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -297,6 +297,7 @@ static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth, } hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif); + hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif); hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT; hw_ioctxt.cmdq_depth = 0; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index b069045de416..66fd2340d447 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -151,8 +151,8 @@ struct hinic_cmd_hw_ioctxt { u8 lro_en; u8 rsvd3; + u8 ppf_idx; u8 rsvd4; - u8 rsvd5; u16 rq_depth; u16 rx_buf_sz_idx; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h index 517794509eb2..c7bb9ceca72c 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h @@ -137,6 +137,7 @@ #define HINIC_HWIF_FUNC_IDX(hwif) ((hwif)->attr.func_idx) #define HINIC_HWIF_PCI_INTF(hwif) ((hwif)->attr.pci_intf_idx) #define HINIC_HWIF_PF_IDX(hwif) ((hwif)->attr.pf_idx) +#define HINIC_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx) #define HINIC_FUNC_TYPE(hwif) ((hwif)->attr.func_type) #define HINIC_IS_PF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PF) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h index f4a339b10b10..79091e131418 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h @@ -94,6 +94,7 @@ struct hinic_rq { struct hinic_wq *wq; + struct cpumask affinity_mask; u32 irq; u16 msix_entry; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 2411ad270c98..42d00b049c6e 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -356,7 +356,8 @@ static void hinic_enable_rss(struct hinic_dev *nic_dev) if (!num_cpus) num_cpus = num_online_cpus(); - nic_dev->num_qps = min_t(u16, nic_dev->max_qps, num_cpus); + nic_dev->num_qps = hinic_hwdev_num_qps(hwdev); + nic_dev->num_qps = min_t(u16, nic_dev->num_qps, num_cpus); nic_dev->rss_limit = nic_dev->num_qps; nic_dev->num_rss = nic_dev->num_qps; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c index 56ea6d692f1c..2695ad69fca6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c @@ -475,7 +475,6 @@ static int rx_request_irq(struct hinic_rxq *rxq) struct hinic_hwdev *hwdev = nic_dev->hwdev; struct hinic_rq *rq = rxq->rq; struct hinic_qp *qp; - struct cpumask mask; int err; rx_add_napi(rxq); @@ -492,8 +491,8 @@ static int rx_request_irq(struct hinic_rxq *rxq) } qp = container_of(rq, struct hinic_qp, rq); - cpumask_set_cpu(qp->q_id % num_online_cpus(), &mask); - return irq_set_affinity_hint(rq->irq, &mask); + cpumask_set_cpu(qp->q_id % num_online_cpus(), &rq->affinity_mask); + return irq_set_affinity_hint(rq->irq, &rq->affinity_mask); } static void rx_free_irq(struct hinic_rxq *rxq) diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 1fe9f6050635..62673e27af0e 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -2916,13 +2916,6 @@ ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) else return -EINVAL; - /* Tell the OS link is going down, the link will go back up when fw - * says it is ready asynchronously - */ - ice_print_link_msg(vsi, false); - netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); - /* Set the FC mode and only restart AN if link is up */ status = ice_set_fc(pi, &aq_failures, link_up); diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 6b1a81df1465..a10ae28ebc8a 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2804,11 +2804,10 @@ static int mvneta_poll(struct napi_struct *napi, int budget) /* For the case where the last mvneta_poll did not process all * RX packets */ - rx_queue = fls(((cause_rx_tx >> 8) & 0xff)); - cause_rx_tx |= pp->neta_armada3700 ? pp->cause_rx_tx : port->cause_rx_tx; + rx_queue = fls(((cause_rx_tx >> 8) & 0xff)); if (rx_queue) { rx_queue = rx_queue - 1; if (pp->bm_priv) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 9c8427698238..55ceabf077b2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -371,6 +371,7 @@ enum { struct mlx5e_sq_wqe_info { u8 opcode; + u8 num_wqebbs; /* Auxiliary data for different opcodes. */ union { @@ -1058,6 +1059,7 @@ int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_state); void mlx5e_activate_rq(struct mlx5e_rq *rq); void mlx5e_deactivate_rq(struct mlx5e_rq *rq); void mlx5e_free_rx_descs(struct mlx5e_rq *rq); +void mlx5e_free_rx_in_progress_descs(struct mlx5e_rq *rq); void mlx5e_activate_icosq(struct mlx5e_icosq *icosq); void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/health.h b/drivers/net/ethernet/mellanox/mlx5/core/en/health.h index d3693fa547ac..e54f70d9af22 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/health.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/health.h @@ -10,8 +10,7 @@ static inline bool cqe_syndrome_needs_recover(u8 syndrome) { - return syndrome == MLX5_CQE_SYNDROME_LOCAL_LENGTH_ERR || - syndrome == MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR || + return syndrome == MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR || syndrome == MLX5_CQE_SYNDROME_LOCAL_PROT_ERR || syndrome == MLX5_CQE_SYNDROME_WR_FLUSH_ERR; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c index b860569d4247..9fa4b98001d5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c @@ -90,7 +90,7 @@ static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx) goto out; mlx5e_reset_icosq_cc_pc(icosq); - mlx5e_free_rx_descs(rq); + mlx5e_free_rx_in_progress_descs(rq); clear_bit(MLX5E_SQ_STATE_RECOVERING, &icosq->state); mlx5e_activate_icosq(icosq); mlx5e_activate_rq(rq); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index a226277b0980..f07b1399744e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -181,10 +181,12 @@ mlx5e_tx_dma_unmap(struct device *pdev, struct mlx5e_sq_dma *dma) static inline void mlx5e_rqwq_reset(struct mlx5e_rq *rq) { - if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) + if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { mlx5_wq_ll_reset(&rq->mpwqe.wq); - else + rq->mpwqe.actual_wq_head = 0; + } else { mlx5_wq_cyc_reset(&rq->wqe.wq); + } } /* SW parser related functions */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index e5e91cbcbc31..ee7c753e9ea0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -824,6 +824,29 @@ int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq, int wait_time) return -ETIMEDOUT; } +void mlx5e_free_rx_in_progress_descs(struct mlx5e_rq *rq) +{ + struct mlx5_wq_ll *wq; + u16 head; + int i; + + if (rq->wq_type != MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) + return; + + wq = &rq->mpwqe.wq; + head = wq->head; + + /* Outstanding UMR WQEs (in progress) start at wq->head */ + for (i = 0; i < rq->mpwqe.umr_in_progress; i++) { + rq->dealloc_wqe(rq, head); + head = mlx5_wq_ll_get_wqe_next_ix(wq, head); + } + + rq->mpwqe.actual_wq_head = wq->head; + rq->mpwqe.umr_in_progress = 0; + rq->mpwqe.umr_completed = 0; +} + void mlx5e_free_rx_descs(struct mlx5e_rq *rq) { __be16 wqe_ix_be; @@ -831,14 +854,8 @@ void mlx5e_free_rx_descs(struct mlx5e_rq *rq) if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { struct mlx5_wq_ll *wq = &rq->mpwqe.wq; - u16 head = wq->head; - int i; - /* Outstanding UMR WQEs (in progress) start at wq->head */ - for (i = 0; i < rq->mpwqe.umr_in_progress; i++) { - rq->dealloc_wqe(rq, head); - head = mlx5_wq_ll_get_wqe_next_ix(wq, head); - } + mlx5e_free_rx_in_progress_descs(rq); while (!mlx5_wq_ll_is_empty(wq)) { struct mlx5e_rx_wqe_ll *wqe; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 82cffb3a9964..1d295a7afc8c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -477,6 +477,7 @@ static inline void mlx5e_fill_icosq_frag_edge(struct mlx5e_icosq *sq, /* fill sq frag edge with nops to avoid wqe wrapping two pages */ for (; wi < edge_wi; wi++) { wi->opcode = MLX5_OPCODE_NOP; + wi->num_wqebbs = 1; mlx5e_post_nop(wq, sq->sqn, &sq->pc); } } @@ -525,6 +526,7 @@ static int mlx5e_alloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix) umr_wqe->uctrl.xlt_offset = cpu_to_be16(xlt_offset); sq->db.ico_wqe[pi].opcode = MLX5_OPCODE_UMR; + sq->db.ico_wqe[pi].num_wqebbs = MLX5E_UMR_WQEBBS; sq->db.ico_wqe[pi].umr.rq = rq; sq->pc += MLX5E_UMR_WQEBBS; @@ -628,17 +630,14 @@ void mlx5e_poll_ico_cq(struct mlx5e_cq *cq) ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sqcc); wi = &sq->db.ico_wqe[ci]; + sqcc += wi->num_wqebbs; - if (likely(wi->opcode == MLX5_OPCODE_UMR)) { - sqcc += MLX5E_UMR_WQEBBS; + if (likely(wi->opcode == MLX5_OPCODE_UMR)) wi->umr.rq->mpwqe.umr_completed++; - } else if (likely(wi->opcode == MLX5_OPCODE_NOP)) { - sqcc++; - } else { + else if (unlikely(wi->opcode != MLX5_OPCODE_NOP)) netdev_WARN_ONCE(cq->channel->netdev, "Bad OPCODE in ICOSQ WQE info: 0x%x\n", wi->opcode); - } } while (!last_wqe); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c index 257a7c9f7a14..800d34ed8a96 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c @@ -78,6 +78,7 @@ void mlx5e_trigger_irq(struct mlx5e_icosq *sq) u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc); sq->db.ico_wqe[pi].opcode = MLX5_OPCODE_NOP; + sq->db.ico_wqe[pi].num_wqebbs = 1; nopwqe = mlx5e_post_nop(wq, sq->sqn, &sq->pc); mlx5e_notify_hw(wq, sq->pc, sq->uar_map, &nopwqe->ctrl); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c index 004c56c2fc0c..b2dfa2b5366f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c @@ -930,7 +930,6 @@ static int dr_actions_l2_rewrite(struct mlx5dr_domain *dmn, action->rewrite.data = (void *)ops; action->rewrite.num_of_actions = i; - action->rewrite.chunk->byte_size = i * sizeof(*ops); ret = mlx5dr_send_postsend_action(dmn, action); if (ret) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c index c7f10d4f8f8d..095ec7b1399d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c @@ -558,7 +558,8 @@ int mlx5dr_send_postsend_action(struct mlx5dr_domain *dmn, int ret; send_info.write.addr = (uintptr_t)action->rewrite.data; - send_info.write.length = action->rewrite.chunk->byte_size; + send_info.write.length = action->rewrite.num_of_actions * + DR_MODIFY_ACTION_SIZE; send_info.write.lkey = 0; send_info.remote_addr = action->rewrite.chunk->mr_addr; send_info.rkey = action->rewrite.chunk->rkey; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c index 2739ed2a2911..841abe75652c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c @@ -2257,7 +2257,9 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, struct mlx5dr_cmd_vport_cap *vport_cap; struct mlx5dr_domain *dmn = sb->dmn; struct mlx5dr_cmd_caps *caps; + u8 *bit_mask = sb->bit_mask; u8 *tag = hw_ste->tag; + bool source_gvmi_set; DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn); @@ -2278,7 +2280,8 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, if (!vport_cap) return -EINVAL; - if (vport_cap->vport_gvmi) + source_gvmi_set = MLX5_GET(ste_src_gvmi_qp, bit_mask, source_gvmi); + if (vport_cap->vport_gvmi && source_gvmi_set) MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi); misc->source_eswitch_owner_vhca_id = 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 615455a21567..f3d1f9411d10 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1318,36 +1318,64 @@ static void mlxsw_pci_mbox_free(struct mlxsw_pci *mlxsw_pci, mbox->mapaddr); } -static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci, - const struct pci_device_id *id) +static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci, + const struct pci_device_id *id, + u32 *p_sys_status) { unsigned long end; - char mrsr_pl[MLXSW_REG_MRSR_LEN]; - int err; + u32 val; - mlxsw_reg_mrsr_pack(mrsr_pl); - err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl); - if (err) - return err; if (id->device == PCI_DEVICE_ID_MELLANOX_SWITCHX2) { msleep(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS); return 0; } - /* We must wait for the HW to become responsive once again. */ + /* We must wait for the HW to become responsive. */ msleep(MLXSW_PCI_SW_RESET_WAIT_MSECS); end = jiffies + msecs_to_jiffies(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS); do { - u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY); - + val = mlxsw_pci_read32(mlxsw_pci, FW_READY); if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC) return 0; cond_resched(); } while (time_before(jiffies, end)); + + *p_sys_status = val & MLXSW_PCI_FW_READY_MASK; + return -EBUSY; } +static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci, + const struct pci_device_id *id) +{ + struct pci_dev *pdev = mlxsw_pci->pdev; + char mrsr_pl[MLXSW_REG_MRSR_LEN]; + u32 sys_status; + int err; + + err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status); + if (err) { + dev_err(&pdev->dev, "Failed to reach system ready status before reset. Status is 0x%x\n", + sys_status); + return err; + } + + mlxsw_reg_mrsr_pack(mrsr_pl); + err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl); + if (err) + return err; + + err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status); + if (err) { + dev_err(&pdev->dev, "Failed to reach system ready status after reset. Status is 0x%x\n", + sys_status); + return err; + } + + return 0; +} + static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci) { int err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c index 54275624718b..336e5ecc68f8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c @@ -637,12 +637,12 @@ static int mlxsw_sp_mr_vif_resolve(struct mlxsw_sp_mr_table *mr_table, return 0; err_erif_unresolve: - list_for_each_entry_from_reverse(erve, &mr_vif->route_evif_list, - vif_node) + list_for_each_entry_continue_reverse(erve, &mr_vif->route_evif_list, + vif_node) mlxsw_sp_mr_route_evif_unresolve(mr_table, erve); err_irif_unresolve: - list_for_each_entry_from_reverse(irve, &mr_vif->route_ivif_list, - vif_node) + list_for_each_entry_continue_reverse(irve, &mr_vif->route_ivif_list, + vif_node) mlxsw_sp_mr_route_ivif_unresolve(mr_table, irve); mr_vif->rif = NULL; return err; diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index a41a90c589db..45cc840d8e2e 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -157,21 +157,47 @@ static int msg_enable; */ /** - * ks_rdreg8 - read 8 bit register from device + * ks_check_endian - Check whether endianness of the bus is correct * @ks : The chip information - * @offset: The register address * - * Read a 8bit register from the chip, returning the result + * The KS8851-16MLL EESK pin allows selecting the endianness of the 16bit + * bus. To maintain optimum performance, the bus endianness should be set + * such that it matches the endianness of the CPU. */ -static u8 ks_rdreg8(struct ks_net *ks, int offset) + +static int ks_check_endian(struct ks_net *ks) { - u16 data; - u8 shift_bit = offset & 0x03; - u8 shift_data = (offset & 1) << 3; - ks->cmd_reg_cache = (u16) offset | (u16)(BE0 << shift_bit); - iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); - data = ioread16(ks->hw_addr); - return (u8)(data >> shift_data); + u16 cider; + + /* + * Read CIDER register first, however read it the "wrong" way around. + * If the endian strap on the KS8851-16MLL in incorrect and the chip + * is operating in different endianness than the CPU, then the meaning + * of BE[3:0] byte-enable bits is also swapped such that: + * BE[3,2,1,0] becomes BE[1,0,3,2] + * + * Luckily for us, the byte-enable bits are the top four MSbits of + * the address register and the CIDER register is at offset 0xc0. + * Hence, by reading address 0xc0c0, which is not impacted by endian + * swapping, we assert either BE[3:2] or BE[1:0] while reading the + * CIDER register. + * + * If the bus configuration is correct, reading 0xc0c0 asserts + * BE[3:2] and this read returns 0x0000, because to read register + * with bottom two LSbits of address set to 0, BE[1:0] must be + * asserted. + * + * If the bus configuration is NOT correct, reading 0xc0c0 asserts + * BE[1:0] and this read returns non-zero 0x8872 value. + */ + iowrite16(BE3 | BE2 | KS_CIDER, ks->hw_addr_cmd); + cider = ioread16(ks->hw_addr); + if (!cider) + return 0; + + netdev_err(ks->netdev, "incorrect EESK endian strap setting\n"); + + return -EINVAL; } /** @@ -189,22 +215,6 @@ static u16 ks_rdreg16(struct ks_net *ks, int offset) return ioread16(ks->hw_addr); } -/** - * ks_wrreg8 - write 8bit register value to chip - * @ks: The chip information - * @offset: The register address - * @value: The value to write - * - */ -static void ks_wrreg8(struct ks_net *ks, int offset, u8 value) -{ - u8 shift_bit = (offset & 0x03); - u16 value_write = (u16)(value << ((offset & 1) << 3)); - ks->cmd_reg_cache = (u16)offset | (BE0 << shift_bit); - iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd); - iowrite16(value_write, ks->hw_addr); -} - /** * ks_wrreg16 - write 16bit register value to chip * @ks: The chip information @@ -324,8 +334,7 @@ static void ks_read_config(struct ks_net *ks) u16 reg_data = 0; /* Regardless of bus width, 8 bit read should always work.*/ - reg_data = ks_rdreg8(ks, KS_CCR) & 0x00FF; - reg_data |= ks_rdreg8(ks, KS_CCR+1) << 8; + reg_data = ks_rdreg16(ks, KS_CCR); /* addr/data bus are multiplexed */ ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED; @@ -429,7 +438,7 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len) /* 1. set sudo DMA mode */ ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI); - ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff); + ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); /* 2. read prepend data */ /** @@ -446,7 +455,7 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len) ks_inblk(ks, buf, ALIGN(len, 4)); /* 4. reset sudo DMA Mode */ - ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr); + ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); } /** @@ -548,14 +557,17 @@ static irqreturn_t ks_irq(int irq, void *pw) { struct net_device *netdev = pw; struct ks_net *ks = netdev_priv(netdev); + unsigned long flags; u16 status; + spin_lock_irqsave(&ks->statelock, flags); /*this should be the first in IRQ handler */ ks_save_cmd_reg(ks); status = ks_rdreg16(ks, KS_ISR); if (unlikely(!status)) { ks_restore_cmd_reg(ks); + spin_unlock_irqrestore(&ks->statelock, flags); return IRQ_NONE; } @@ -581,6 +593,7 @@ static irqreturn_t ks_irq(int irq, void *pw) ks->netdev->stats.rx_over_errors++; /* this should be the last in IRQ handler*/ ks_restore_cmd_reg(ks); + spin_unlock_irqrestore(&ks->statelock, flags); return IRQ_HANDLED; } @@ -650,6 +663,7 @@ static int ks_net_stop(struct net_device *netdev) /* shutdown RX/TX QMU */ ks_disable_qmu(ks); + ks_disable_int(ks); /* set powermode to soft power down to save power */ ks_set_powermode(ks, PMECR_PM_SOFTDOWN); @@ -679,13 +693,13 @@ static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len) ks->txh.txw[1] = cpu_to_le16(len); /* 1. set sudo-DMA mode */ - ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff); + ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA); /* 2. write status/lenth info */ ks_outblk(ks, ks->txh.txw, 4); /* 3. write pkt data */ ks_outblk(ks, (u16 *)pdata, ALIGN(len, 4)); /* 4. reset sudo-DMA mode */ - ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr); + ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); /* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */ ks_wrreg16(ks, KS_TXQCR, TXQCR_METFE); /* 6. wait until TXQCR_METFE is auto-cleared */ @@ -706,10 +720,9 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev) { netdev_tx_t retv = NETDEV_TX_OK; struct ks_net *ks = netdev_priv(netdev); + unsigned long flags; - disable_irq(netdev->irq); - ks_disable_int(ks); - spin_lock(&ks->statelock); + spin_lock_irqsave(&ks->statelock, flags); /* Extra space are required: * 4 byte for alignment, 4 for status/length, 4 for CRC @@ -723,9 +736,7 @@ static netdev_tx_t ks_start_xmit(struct sk_buff *skb, struct net_device *netdev) dev_kfree_skb(skb); } else retv = NETDEV_TX_BUSY; - spin_unlock(&ks->statelock); - ks_enable_int(ks); - enable_irq(netdev->irq); + spin_unlock_irqrestore(&ks->statelock, flags); return retv; } @@ -1251,6 +1262,10 @@ static int ks8851_probe(struct platform_device *pdev) goto err_free; } + err = ks_check_endian(ks); + if (err) + goto err_free; + netdev->irq = platform_get_irq(pdev, 0); if ((int)netdev->irq < 0) { diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index 06de59521fc4..fbf4cbcf1a65 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -13,25 +13,6 @@ #include "rmnet_vnd.h" #include "rmnet_private.h" -/* Locking scheme - - * The shared resource which needs to be protected is realdev->rx_handler_data. - * For the writer path, this is using rtnl_lock(). The writer paths are - * rmnet_newlink(), rmnet_dellink() and rmnet_force_unassociate_device(). These - * paths are already called with rtnl_lock() acquired in. There is also an - * ASSERT_RTNL() to ensure that we are calling with rtnl acquired. For - * dereference here, we will need to use rtnl_dereference(). Dev list writing - * needs to happen with rtnl_lock() acquired for netdev_master_upper_dev_link(). - * For the reader path, the real_dev->rx_handler_data is called in the TX / RX - * path. We only need rcu_read_lock() for these scenarios. In these cases, - * the rcu_read_lock() is held in __dev_queue_xmit() and - * netif_receive_skb_internal(), so readers need to use rcu_dereference_rtnl() - * to get the relevant information. For dev list reading, we again acquire - * rcu_read_lock() in rmnet_dellink() for netdev_master_upper_dev_get_rcu(). - * We also use unregister_netdevice_many() to free all rmnet devices in - * rmnet_force_unassociate_device() so we dont lose the rtnl_lock() and free in - * same context. - */ - /* Local Definitions and Declarations */ static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 1] = { @@ -51,9 +32,10 @@ rmnet_get_port_rtnl(const struct net_device *real_dev) return rtnl_dereference(real_dev->rx_handler_data); } -static int rmnet_unregister_real_device(struct net_device *real_dev, - struct rmnet_port *port) +static int rmnet_unregister_real_device(struct net_device *real_dev) { + struct rmnet_port *port = rmnet_get_port_rtnl(real_dev); + if (port->nr_rmnet_devs) return -EINVAL; @@ -61,9 +43,6 @@ static int rmnet_unregister_real_device(struct net_device *real_dev, kfree(port); - /* release reference on real_dev */ - dev_put(real_dev); - netdev_dbg(real_dev, "Removed from rmnet\n"); return 0; } @@ -89,9 +68,6 @@ static int rmnet_register_real_device(struct net_device *real_dev) return -EBUSY; } - /* hold on to real dev for MAP data */ - dev_hold(real_dev); - for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++) INIT_HLIST_HEAD(&port->muxed_ep[entry]); @@ -99,28 +75,33 @@ static int rmnet_register_real_device(struct net_device *real_dev) return 0; } -static void rmnet_unregister_bridge(struct net_device *dev, - struct rmnet_port *port) +static void rmnet_unregister_bridge(struct rmnet_port *port) { - struct rmnet_port *bridge_port; - struct net_device *bridge_dev; + struct net_device *bridge_dev, *real_dev, *rmnet_dev; + struct rmnet_port *real_port; if (port->rmnet_mode != RMNET_EPMODE_BRIDGE) return; - /* bridge slave handling */ + rmnet_dev = port->rmnet_dev; if (!port->nr_rmnet_devs) { - bridge_dev = port->bridge_ep; + /* bridge device */ + real_dev = port->bridge_ep; + bridge_dev = port->dev; - bridge_port = rmnet_get_port_rtnl(bridge_dev); - bridge_port->bridge_ep = NULL; - bridge_port->rmnet_mode = RMNET_EPMODE_VND; + real_port = rmnet_get_port_rtnl(real_dev); + real_port->bridge_ep = NULL; + real_port->rmnet_mode = RMNET_EPMODE_VND; } else { + /* real device */ bridge_dev = port->bridge_ep; - bridge_port = rmnet_get_port_rtnl(bridge_dev); - rmnet_unregister_real_device(bridge_dev, bridge_port); + port->bridge_ep = NULL; + port->rmnet_mode = RMNET_EPMODE_VND; } + + netdev_upper_dev_unlink(bridge_dev, rmnet_dev); + rmnet_unregister_real_device(bridge_dev); } static int rmnet_newlink(struct net *src_net, struct net_device *dev, @@ -135,6 +116,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, int err = 0; u16 mux_id; + if (!tb[IFLA_LINK]) { + NL_SET_ERR_MSG_MOD(extack, "link not specified"); + return -EINVAL; + } + real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev || !dev) return -ENODEV; @@ -157,7 +143,12 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, if (err) goto err1; + err = netdev_upper_dev_link(real_dev, dev, extack); + if (err < 0) + goto err2; + port->rmnet_mode = mode; + port->rmnet_dev = dev; hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]); @@ -173,8 +164,11 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev, return 0; +err2: + unregister_netdevice(dev); + rmnet_vnd_dellink(mux_id, port, ep); err1: - rmnet_unregister_real_device(real_dev, port); + rmnet_unregister_real_device(real_dev); err0: kfree(ep); return err; @@ -183,77 +177,74 @@ err0: static void rmnet_dellink(struct net_device *dev, struct list_head *head) { struct rmnet_priv *priv = netdev_priv(dev); - struct net_device *real_dev; + struct net_device *real_dev, *bridge_dev; + struct rmnet_port *real_port, *bridge_port; struct rmnet_endpoint *ep; - struct rmnet_port *port; - u8 mux_id; + u8 mux_id = priv->mux_id; real_dev = priv->real_dev; - if (!real_dev || !rmnet_is_real_dev_registered(real_dev)) + if (!rmnet_is_real_dev_registered(real_dev)) return; - port = rmnet_get_port_rtnl(real_dev); + real_port = rmnet_get_port_rtnl(real_dev); + bridge_dev = real_port->bridge_ep; + if (bridge_dev) { + bridge_port = rmnet_get_port_rtnl(bridge_dev); + rmnet_unregister_bridge(bridge_port); + } - mux_id = rmnet_vnd_get_mux(dev); - - ep = rmnet_get_endpoint(port, mux_id); + ep = rmnet_get_endpoint(real_port, mux_id); if (ep) { hlist_del_init_rcu(&ep->hlnode); - rmnet_unregister_bridge(dev, port); - rmnet_vnd_dellink(mux_id, port, ep); + rmnet_vnd_dellink(mux_id, real_port, ep); kfree(ep); } - rmnet_unregister_real_device(real_dev, port); + netdev_upper_dev_unlink(real_dev, dev); + rmnet_unregister_real_device(real_dev); unregister_netdevice_queue(dev, head); } -static void rmnet_force_unassociate_device(struct net_device *dev) +static void rmnet_force_unassociate_device(struct net_device *real_dev) { - struct net_device *real_dev = dev; struct hlist_node *tmp_ep; struct rmnet_endpoint *ep; struct rmnet_port *port; unsigned long bkt_ep; LIST_HEAD(list); - if (!rmnet_is_real_dev_registered(real_dev)) - return; + port = rmnet_get_port_rtnl(real_dev); - ASSERT_RTNL(); - - port = rmnet_get_port_rtnl(dev); - - rcu_read_lock(); - rmnet_unregister_bridge(dev, port); - - hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) { - unregister_netdevice_queue(ep->egress_dev, &list); - rmnet_vnd_dellink(ep->mux_id, port, ep); - - hlist_del_init_rcu(&ep->hlnode); - kfree(ep); + if (port->nr_rmnet_devs) { + /* real device */ + rmnet_unregister_bridge(port); + hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) { + unregister_netdevice_queue(ep->egress_dev, &list); + netdev_upper_dev_unlink(real_dev, ep->egress_dev); + rmnet_vnd_dellink(ep->mux_id, port, ep); + hlist_del_init_rcu(&ep->hlnode); + kfree(ep); + } + rmnet_unregister_real_device(real_dev); + unregister_netdevice_many(&list); + } else { + rmnet_unregister_bridge(port); } - - rcu_read_unlock(); - unregister_netdevice_many(&list); - - rmnet_unregister_real_device(real_dev, port); } static int rmnet_config_notify_cb(struct notifier_block *nb, unsigned long event, void *data) { - struct net_device *dev = netdev_notifier_info_to_dev(data); + struct net_device *real_dev = netdev_notifier_info_to_dev(data); - if (!dev) + if (!rmnet_is_real_dev_registered(real_dev)) return NOTIFY_DONE; switch (event) { case NETDEV_UNREGISTER: - netdev_dbg(dev, "Kernel unregister\n"); - rmnet_force_unassociate_device(dev); + netdev_dbg(real_dev, "Kernel unregister\n"); + rmnet_force_unassociate_device(real_dev); break; default: @@ -295,16 +286,18 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[], if (!dev) return -ENODEV; - real_dev = __dev_get_by_index(dev_net(dev), - nla_get_u32(tb[IFLA_LINK])); - - if (!real_dev || !rmnet_is_real_dev_registered(real_dev)) + real_dev = priv->real_dev; + if (!rmnet_is_real_dev_registered(real_dev)) return -ENODEV; port = rmnet_get_port_rtnl(real_dev); if (data[IFLA_RMNET_MUX_ID]) { mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]); + if (rmnet_get_endpoint(port, mux_id)) { + NL_SET_ERR_MSG_MOD(extack, "MUX ID already exists"); + return -EINVAL; + } ep = rmnet_get_endpoint(port, priv->mux_id); if (!ep) return -ENODEV; @@ -379,11 +372,10 @@ struct rtnl_link_ops rmnet_link_ops __read_mostly = { .fill_info = rmnet_fill_info, }; -/* Needs either rcu_read_lock() or rtnl lock */ -struct rmnet_port *rmnet_get_port(struct net_device *real_dev) +struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev) { if (rmnet_is_real_dev_registered(real_dev)) - return rcu_dereference_rtnl(real_dev->rx_handler_data); + return rcu_dereference_bh(real_dev->rx_handler_data); else return NULL; } @@ -409,7 +401,7 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, struct rmnet_port *port, *slave_port; int err; - port = rmnet_get_port(real_dev); + port = rmnet_get_port_rtnl(real_dev); /* If there is more than one rmnet dev attached, its probably being * used for muxing. Skip the briding in that case @@ -417,6 +409,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, if (port->nr_rmnet_devs > 1) return -EINVAL; + if (port->rmnet_mode != RMNET_EPMODE_VND) + return -EINVAL; + if (rmnet_is_real_dev_registered(slave_dev)) return -EBUSY; @@ -424,9 +419,17 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, if (err) return -EBUSY; - slave_port = rmnet_get_port(slave_dev); + err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL, + extack); + if (err) { + rmnet_unregister_real_device(slave_dev); + return err; + } + + slave_port = rmnet_get_port_rtnl(slave_dev); slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE; slave_port->bridge_ep = real_dev; + slave_port->rmnet_dev = rmnet_dev; port->rmnet_mode = RMNET_EPMODE_BRIDGE; port->bridge_ep = slave_dev; @@ -438,16 +441,9 @@ int rmnet_add_bridge(struct net_device *rmnet_dev, int rmnet_del_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev) { - struct rmnet_priv *priv = netdev_priv(rmnet_dev); - struct net_device *real_dev = priv->real_dev; - struct rmnet_port *port, *slave_port; + struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev); - port = rmnet_get_port(real_dev); - port->rmnet_mode = RMNET_EPMODE_VND; - port->bridge_ep = NULL; - - slave_port = rmnet_get_port(slave_dev); - rmnet_unregister_real_device(slave_dev, slave_port); + rmnet_unregister_bridge(port); netdev_dbg(slave_dev, "removed from rmnet as slave\n"); return 0; @@ -473,8 +469,8 @@ static int __init rmnet_init(void) static void __exit rmnet_exit(void) { - unregister_netdevice_notifier(&rmnet_dev_notifier); rtnl_link_unregister(&rmnet_link_ops); + unregister_netdevice_notifier(&rmnet_dev_notifier); } module_init(rmnet_init) diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h index cd0a6bcbe74a..be515982d628 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h @@ -28,6 +28,7 @@ struct rmnet_port { u8 rmnet_mode; struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP]; struct net_device *bridge_ep; + struct net_device *rmnet_dev; }; extern struct rtnl_link_ops rmnet_link_ops; @@ -65,7 +66,7 @@ struct rmnet_priv { struct rmnet_priv_stats stats; }; -struct rmnet_port *rmnet_get_port(struct net_device *real_dev); +struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev); struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id); int rmnet_add_bridge(struct net_device *rmnet_dev, struct net_device *slave_dev, diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c index 1b74bc160402..29a7bfa2584d 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c @@ -159,6 +159,9 @@ static int rmnet_map_egress_handler(struct sk_buff *skb, static void rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev) { + if (skb_mac_header_was_set(skb)) + skb_push(skb, skb->mac_len); + if (bridge_dev) { skb->dev = bridge_dev; dev_queue_xmit(skb); @@ -184,7 +187,7 @@ rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) return RX_HANDLER_PASS; dev = skb->dev; - port = rmnet_get_port(dev); + port = rmnet_get_port_rcu(dev); switch (port->rmnet_mode) { case RMNET_EPMODE_VND: @@ -217,7 +220,7 @@ void rmnet_egress_handler(struct sk_buff *skb) skb->dev = priv->real_dev; mux_id = priv->mux_id; - port = rmnet_get_port(skb->dev); + port = rmnet_get_port_rcu(skb->dev); if (!port) goto drop; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c index 509dfc895a33..26ad40f19c64 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c @@ -266,14 +266,6 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port, return 0; } -u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev) -{ - struct rmnet_priv *priv; - - priv = netdev_priv(rmnet_dev); - return priv->mux_id; -} - int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable) { netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable); diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h index 54cbaf3c3bc4..14d77c709d4a 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h @@ -16,6 +16,5 @@ int rmnet_vnd_dellink(u8 id, struct rmnet_port *port, struct rmnet_endpoint *ep); void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev); void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev); -u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev); void rmnet_vnd_setup(struct net_device *dev); #endif /* _RMNET_VND_H_ */ diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index a2cef6a004e7..5ebfc3e66331 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -6812,7 +6812,7 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable); rtl_lock_config_regs(tp); /* fall through */ - case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_24: + case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_17: flags = PCI_IRQ_LEGACY; break; default: @@ -6903,6 +6903,13 @@ static int r8169_mdio_register(struct rtl8169_private *tp) if (!tp->phydev) { mdiobus_unregister(new_bus); return -ENODEV; + } else if (!tp->phydev->drv) { + /* Most chip versions fail with the genphy driver. + * Therefore ensure that the dedicated PHY driver is loaded. + */ + dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n"); + mdiobus_unregister(new_bus); + return -EUNATCH; } /* PHY will be woken up in rtl_open() */ @@ -7064,15 +7071,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) int chipset, region; int jumbo_max, rc; - /* Some tools for creating an initramfs don't consider softdeps, then - * r8169.ko may be in initramfs, but realtek.ko not. Then the generic - * PHY driver is used that doesn't work with most chip versions. - */ - if (!driver_find("RTL8201CP Ethernet", &mdio_bus_type)) { - dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n"); - return -ENOENT; - } - dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp)); if (!dev) return -ENOMEM; diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c index c56fcbb37066..38767d797914 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c @@ -2279,7 +2279,7 @@ static int __init sxgbe_cmdline_opt(char *str) if (!str || !*str) return -EINVAL; while ((opt = strsep(&str, ",")) != NULL) { - if (!strncmp(opt, "eee_timer:", 6)) { + if (!strncmp(opt, "eee_timer:", 10)) { if (kstrtoint(opt + 10, 0, &eee_timer)) goto err; } diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 2fef7402233e..82391abbd42b 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -519,6 +519,7 @@ efx_copy_channel(const struct efx_channel *old_channel) if (tx_queue->channel) tx_queue->channel = channel; tx_queue->buffer = NULL; + tx_queue->cb_page = NULL; memset(&tx_queue->txd, 0, sizeof(tx_queue->txd)); } diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index af15a737c675..59b4f16896a8 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -560,13 +560,45 @@ efx_ptp_mac_nic_to_ktime_correction(struct efx_nic *efx, u32 nic_major, u32 nic_minor, s32 correction) { + u32 sync_timestamp; ktime_t kt = { 0 }; + s16 delta; if (!(nic_major & 0x80000000)) { WARN_ON_ONCE(nic_major >> 16); - /* Use the top bits from the latest sync event. */ - nic_major &= 0xffff; - nic_major |= (last_sync_timestamp_major(efx) & 0xffff0000); + + /* Medford provides 48 bits of timestamp, so we must get the top + * 16 bits from the timesync event state. + * + * We only have the lower 16 bits of the time now, but we do + * have a full resolution timestamp at some point in past. As + * long as the difference between the (real) now and the sync + * is less than 2^15, then we can reconstruct the difference + * between those two numbers using only the lower 16 bits of + * each. + * + * Put another way + * + * a - b = ((a mod k) - b) mod k + * + * when -k/2 < (a-b) < k/2. In our case k is 2^16. We know + * (a mod k) and b, so can calculate the delta, a - b. + * + */ + sync_timestamp = last_sync_timestamp_major(efx); + + /* Because delta is s16 this does an implicit mask down to + * 16 bits which is what we need, assuming + * MEDFORD_TX_SECS_EVENT_BITS is 16. delta is signed so that + * we can deal with the (unlikely) case of sync timestamps + * arriving from the future. + */ + delta = nic_major - sync_timestamp; + + /* Recover the fully specified time now, by applying the offset + * to the (fully specified) sync time. + */ + nic_major = sync_timestamp + delta; kt = ptp->nic_to_kernel_time(nic_major, nic_minor, correction); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index e2e469c37a4d..9f9aaa47a8dc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -1411,7 +1411,7 @@ static int rk_gmac_probe(struct platform_device *pdev) ret = rk_gmac_clk_init(plat_dat); if (ret) - return ret; + goto err_remove_config_dt; ret = rk_gmac_powerup(plat_dat->bsp_priv); if (ret) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index 3d69da112625..43a785f86c69 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -24,6 +24,7 @@ static void dwmac1000_core_init(struct mac_device_info *hw, struct net_device *dev) { + struct stmmac_priv *priv = netdev_priv(dev); void __iomem *ioaddr = hw->pcsr; u32 value = readl(ioaddr + GMAC_CONTROL); int mtu = dev->mtu; @@ -35,7 +36,7 @@ static void dwmac1000_core_init(struct mac_device_info *hw, * Broadcom tags can look like invalid LLC/SNAP packets and cause the * hardware to truncate packets on reception. */ - if (netdev_uses_dsa(dev)) + if (netdev_uses_dsa(dev) || !priv->plat->enh_desc) value &= ~GMAC_CONTROL_ACS; if (mtu > 1500) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 582176d869c3..89a6ae2b17e3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -4208,6 +4208,8 @@ static void stmmac_init_fs(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); + rtnl_lock(); + /* Create per netdev entries */ priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); @@ -4219,14 +4221,13 @@ static void stmmac_init_fs(struct net_device *dev) debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev, &stmmac_dma_cap_fops); - register_netdevice_notifier(&stmmac_notifier); + rtnl_unlock(); } static void stmmac_exit_fs(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); - unregister_netdevice_notifier(&stmmac_notifier); debugfs_remove_recursive(priv->dbgfs_dir); } #endif /* CONFIG_DEBUG_FS */ @@ -4728,14 +4729,14 @@ int stmmac_dvr_remove(struct device *dev) netdev_info(priv->dev, "%s: removing driver", __func__); -#ifdef CONFIG_DEBUG_FS - stmmac_exit_fs(ndev); -#endif stmmac_stop_all_dma(priv); stmmac_mac_set(priv, priv->ioaddr, false); netif_carrier_off(ndev); unregister_netdev(ndev); +#ifdef CONFIG_DEBUG_FS + stmmac_exit_fs(ndev); +#endif phylink_destroy(priv->phylink); if (priv->plat->stmmac_rst) reset_control_assert(priv->plat->stmmac_rst); @@ -4955,6 +4956,7 @@ static int __init stmmac_init(void) /* Create debugfs main directory if it doesn't exist yet */ if (!stmmac_fs_dir) stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); + register_netdevice_notifier(&stmmac_notifier); #endif return 0; @@ -4963,6 +4965,7 @@ static int __init stmmac_init(void) static void __exit stmmac_exit(void) { #ifdef CONFIG_DEBUG_FS + unregister_netdevice_notifier(&stmmac_notifier); debugfs_remove_recursive(stmmac_fs_dir); #endif } diff --git a/drivers/net/ethernet/xilinx/ll_temac.h b/drivers/net/ethernet/xilinx/ll_temac.h index 276292bca334..53fb8141f1a6 100644 --- a/drivers/net/ethernet/xilinx/ll_temac.h +++ b/drivers/net/ethernet/xilinx/ll_temac.h @@ -375,10 +375,14 @@ struct temac_local { int tx_bd_next; int tx_bd_tail; int rx_bd_ci; + int rx_bd_tail; /* DMA channel control setup */ u32 tx_chnl_ctrl; u32 rx_chnl_ctrl; + u8 coalesce_count_rx; + + struct delayed_work restart_work; }; /* Wrappers for temac_ior()/temac_iow() function pointers above */ diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 21c1b4322ea7..eb480204cdbe 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -367,6 +368,8 @@ static int temac_dma_bd_init(struct net_device *ndev) skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) + goto out; lp->rx_bd_v[i].phys = cpu_to_be32(skb_dma_addr); lp->rx_bd_v[i].len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); lp->rx_bd_v[i].app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND); @@ -387,12 +390,13 @@ static int temac_dma_bd_init(struct net_device *ndev) lp->tx_bd_next = 0; lp->tx_bd_tail = 0; lp->rx_bd_ci = 0; + lp->rx_bd_tail = RX_BD_NUM - 1; /* Enable RX DMA transfers */ wmb(); lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p); lp->dma_out(lp, RX_TAILDESC_PTR, - lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); + lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * lp->rx_bd_tail)); /* Prepare for TX DMA transfer */ lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p); @@ -788,6 +792,9 @@ static void temac_start_xmit_done(struct net_device *ndev) stat = be32_to_cpu(cur_p->app0); } + /* Matches barrier in temac_start_xmit */ + smp_mb(); + netif_wake_queue(ndev); } @@ -830,9 +837,19 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; if (temac_check_tx_bd_space(lp, num_frag + 1)) { - if (!netif_queue_stopped(ndev)) - netif_stop_queue(ndev); - return NETDEV_TX_BUSY; + if (netif_queue_stopped(ndev)) + return NETDEV_TX_BUSY; + + netif_stop_queue(ndev); + + /* Matches barrier in temac_start_xmit_done */ + smp_mb(); + + /* Space might have just been freed - check again */ + if (temac_check_tx_bd_space(lp, num_frag)) + return NETDEV_TX_BUSY; + + netif_wake_queue(ndev); } cur_p->app0 = 0; @@ -850,12 +867,16 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, skb_headlen(skb), DMA_TO_DEVICE); cur_p->len = cpu_to_be32(skb_headlen(skb)); + if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, skb_dma_addr))) { + dev_kfree_skb_any(skb); + ndev->stats.tx_dropped++; + return NETDEV_TX_OK; + } cur_p->phys = cpu_to_be32(skb_dma_addr); ptr_to_txbd((void *)skb, cur_p); for (ii = 0; ii < num_frag; ii++) { - lp->tx_bd_tail++; - if (lp->tx_bd_tail >= TX_BD_NUM) + if (++lp->tx_bd_tail >= TX_BD_NUM) lp->tx_bd_tail = 0; cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; @@ -863,6 +884,27 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) skb_frag_address(frag), skb_frag_size(frag), DMA_TO_DEVICE); + if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) { + if (--lp->tx_bd_tail < 0) + lp->tx_bd_tail = TX_BD_NUM - 1; + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + while (--ii >= 0) { + --frag; + dma_unmap_single(ndev->dev.parent, + be32_to_cpu(cur_p->phys), + skb_frag_size(frag), + DMA_TO_DEVICE); + if (--lp->tx_bd_tail < 0) + lp->tx_bd_tail = TX_BD_NUM - 1; + cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; + } + dma_unmap_single(ndev->dev.parent, + be32_to_cpu(cur_p->phys), + skb_headlen(skb), DMA_TO_DEVICE); + dev_kfree_skb_any(skb); + ndev->stats.tx_dropped++; + return NETDEV_TX_OK; + } cur_p->phys = cpu_to_be32(skb_dma_addr); cur_p->len = cpu_to_be32(skb_frag_size(frag)); cur_p->app0 = 0; @@ -884,31 +926,56 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } +static int ll_temac_recv_buffers_available(struct temac_local *lp) +{ + int available; + + if (!lp->rx_skb[lp->rx_bd_ci]) + return 0; + available = 1 + lp->rx_bd_tail - lp->rx_bd_ci; + if (available <= 0) + available += RX_BD_NUM; + return available; +} static void ll_temac_recv(struct net_device *ndev) { struct temac_local *lp = netdev_priv(ndev); - struct sk_buff *skb, *new_skb; - unsigned int bdstat; - struct cdmac_bd *cur_p; - dma_addr_t tail_p, skb_dma_addr; - int length; unsigned long flags; + int rx_bd; + bool update_tail = false; spin_lock_irqsave(&lp->rx_lock, flags); - tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci; - cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; + /* Process all received buffers, passing them on network + * stack. After this, the buffer descriptors will be in an + * un-allocated stage, where no skb is allocated for it, and + * they are therefore not available for TEMAC/DMA. + */ + do { + struct cdmac_bd *bd = &lp->rx_bd_v[lp->rx_bd_ci]; + struct sk_buff *skb = lp->rx_skb[lp->rx_bd_ci]; + unsigned int bdstat = be32_to_cpu(bd->app0); + int length; - bdstat = be32_to_cpu(cur_p->app0); - while ((bdstat & STS_CTRL_APP0_CMPLT)) { + /* While this should not normally happen, we can end + * here when GFP_ATOMIC allocations fail, and we + * therefore have un-allocated buffers. + */ + if (!skb) + break; - skb = lp->rx_skb[lp->rx_bd_ci]; - length = be32_to_cpu(cur_p->app4) & 0x3FFF; + /* Loop over all completed buffer descriptors */ + if (!(bdstat & STS_CTRL_APP0_CMPLT)) + break; - dma_unmap_single(ndev->dev.parent, be32_to_cpu(cur_p->phys), + dma_unmap_single(ndev->dev.parent, be32_to_cpu(bd->phys), XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE); + /* The buffer is not valid for DMA anymore */ + bd->phys = 0; + bd->len = 0; + length = be32_to_cpu(bd->app4) & 0x3FFF; skb_put(skb, length); skb->protocol = eth_type_trans(skb, ndev); skb_checksum_none_assert(skb); @@ -923,43 +990,102 @@ static void ll_temac_recv(struct net_device *ndev) * (back) for proper IP checksum byte order * (be16). */ - skb->csum = htons(be32_to_cpu(cur_p->app3) & 0xFFFF); + skb->csum = htons(be32_to_cpu(bd->app3) & 0xFFFF); skb->ip_summed = CHECKSUM_COMPLETE; } if (!skb_defer_rx_timestamp(skb)) netif_rx(skb); + /* The skb buffer is now owned by network stack above */ + lp->rx_skb[lp->rx_bd_ci] = NULL; ndev->stats.rx_packets++; ndev->stats.rx_bytes += length; - new_skb = netdev_alloc_skb_ip_align(ndev, - XTE_MAX_JUMBO_FRAME_SIZE); - if (!new_skb) { - spin_unlock_irqrestore(&lp->rx_lock, flags); - return; + rx_bd = lp->rx_bd_ci; + if (++lp->rx_bd_ci >= RX_BD_NUM) + lp->rx_bd_ci = 0; + } while (rx_bd != lp->rx_bd_tail); + + /* DMA operations will halt when the last buffer descriptor is + * processed (ie. the one pointed to by RX_TAILDESC_PTR). + * When that happens, no more interrupt events will be + * generated. No IRQ_COAL or IRQ_DLY, and not even an + * IRQ_ERR. To avoid stalling, we schedule a delayed work + * when there is a potential risk of that happening. The work + * will call this function, and thus re-schedule itself until + * enough buffers are available again. + */ + if (ll_temac_recv_buffers_available(lp) < lp->coalesce_count_rx) + schedule_delayed_work(&lp->restart_work, HZ / 1000); + + /* Allocate new buffers for those buffer descriptors that were + * passed to network stack. Note that GFP_ATOMIC allocations + * can fail (e.g. when a larger burst of GFP_ATOMIC + * allocations occurs), so while we try to allocate all + * buffers in the same interrupt where they were processed, we + * continue with what we could get in case of allocation + * failure. Allocation of remaining buffers will be retried + * in following calls. + */ + while (1) { + struct sk_buff *skb; + struct cdmac_bd *bd; + dma_addr_t skb_dma_addr; + + rx_bd = lp->rx_bd_tail + 1; + if (rx_bd >= RX_BD_NUM) + rx_bd = 0; + bd = &lp->rx_bd_v[rx_bd]; + + if (bd->phys) + break; /* All skb's allocated */ + + skb = netdev_alloc_skb_ip_align(ndev, XTE_MAX_JUMBO_FRAME_SIZE); + if (!skb) { + dev_warn(&ndev->dev, "skb alloc failed\n"); + break; } - cur_p->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND); - skb_dma_addr = dma_map_single(ndev->dev.parent, new_skb->data, + skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data, XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE); - cur_p->phys = cpu_to_be32(skb_dma_addr); - cur_p->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); - lp->rx_skb[lp->rx_bd_ci] = new_skb; + if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, + skb_dma_addr))) { + dev_kfree_skb_any(skb); + break; + } - lp->rx_bd_ci++; - if (lp->rx_bd_ci >= RX_BD_NUM) - lp->rx_bd_ci = 0; + bd->phys = cpu_to_be32(skb_dma_addr); + bd->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE); + bd->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND); + lp->rx_skb[rx_bd] = skb; - cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; - bdstat = be32_to_cpu(cur_p->app0); + lp->rx_bd_tail = rx_bd; + update_tail = true; + } + + /* Move tail pointer when buffers have been allocated */ + if (update_tail) { + lp->dma_out(lp, RX_TAILDESC_PTR, + lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_tail); } - lp->dma_out(lp, RX_TAILDESC_PTR, tail_p); spin_unlock_irqrestore(&lp->rx_lock, flags); } +/* Function scheduled to ensure a restart in case of DMA halt + * condition caused by running out of buffer descriptors. + */ +static void ll_temac_restart_work_func(struct work_struct *work) +{ + struct temac_local *lp = container_of(work, struct temac_local, + restart_work.work); + struct net_device *ndev = lp->ndev; + + ll_temac_recv(ndev); +} + static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev) { struct net_device *ndev = _ndev; @@ -1052,6 +1178,8 @@ static int temac_stop(struct net_device *ndev) dev_dbg(&ndev->dev, "temac_close()\n"); + cancel_delayed_work_sync(&lp->restart_work); + free_irq(lp->tx_irq, ndev); free_irq(lp->rx_irq, ndev); @@ -1184,6 +1312,7 @@ static int temac_probe(struct platform_device *pdev) lp->dev = &pdev->dev; lp->options = XTE_OPTION_DEFAULTS; spin_lock_init(&lp->rx_lock); + INIT_DELAYED_WORK(&lp->restart_work, ll_temac_restart_work_func); /* Setup mutex for synchronization of indirect register access */ if (pdata) { @@ -1290,6 +1419,7 @@ static int temac_probe(struct platform_device *pdev) */ lp->tx_chnl_ctrl = 0x10220000; lp->rx_chnl_ctrl = 0xff070000; + lp->coalesce_count_rx = 0x07; /* Finished with the DMA node; drop the reference */ of_node_put(dma_np); @@ -1321,11 +1451,14 @@ static int temac_probe(struct platform_device *pdev) (pdata->tx_irq_count << 16); else lp->tx_chnl_ctrl = 0x10220000; - if (pdata->rx_irq_timeout || pdata->rx_irq_count) + if (pdata->rx_irq_timeout || pdata->rx_irq_count) { lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) | (pdata->rx_irq_count << 16); - else + lp->coalesce_count_rx = pdata->rx_irq_count; + } else { lp->rx_chnl_ctrl = 0xff070000; + lp->coalesce_count_rx = 0x07; + } } /* Error handle returned DMA RX and TX interrupts */ diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 5c6b7fc04ea6..730ab57201bd 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1845,8 +1845,6 @@ static void geneve_destroy_tunnels(struct net *net, struct list_head *head) if (!net_eq(dev_net(geneve->dev), net)) unregister_netdevice_queue(geneve->dev, head); } - - WARN_ON_ONCE(!list_empty(&gn->sock_list)); } static void __net_exit geneve_exit_batch_net(struct list_head *net_list) @@ -1861,6 +1859,12 @@ static void __net_exit geneve_exit_batch_net(struct list_head *net_list) /* unregister the devices gathered above */ unregister_netdevice_many(&list); rtnl_unlock(); + + list_for_each_entry(net, net_list, exit_list) { + const struct geneve_net *gn = net_generic(net, geneve_net_id); + + WARN_ON_ONCE(!list_empty(&gn->sock_list)); + } } static struct pernet_operations geneve_net_ops = { diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 242b9b0943f8..7fe306e76281 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -75,7 +75,7 @@ static void ifb_ri_tasklet(unsigned long _txp) } while ((skb = __skb_dequeue(&txp->tq)) != NULL) { - skb->tc_redirected = 0; + skb->redirected = 0; skb->tc_skip_classify = 1; u64_stats_update_begin(&txp->tsync); @@ -96,7 +96,7 @@ static void ifb_ri_tasklet(unsigned long _txp) rcu_read_unlock(); skb->skb_iif = txp->dev->ifindex; - if (!skb->tc_from_ingress) { + if (!skb->from_ingress) { dev_queue_xmit(skb); } else { skb_pull_rcsum(skb, skb->mac_len); @@ -243,7 +243,7 @@ static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev) txp->rx_bytes += skb->len; u64_stats_update_end(&txp->rsync); - if (!skb->tc_redirected || !skb->skb_iif) { + if (!skb->redirected || !skb->skb_iif) { dev_kfree_skb(skb); dev->stats.rx_dropped++; return NETDEV_TX_OK; diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 30cd0c4f0be0..8801d093135c 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -293,6 +293,7 @@ void ipvlan_process_multicast(struct work_struct *work) } if (dev) dev_put(dev); + cond_resched(); } } @@ -498,19 +499,21 @@ static int ipvlan_process_outbound(struct sk_buff *skb) struct ethhdr *ethh = eth_hdr(skb); int ret = NET_XMIT_DROP; - /* In this mode we dont care about multicast and broadcast traffic */ - if (is_multicast_ether_addr(ethh->h_dest)) { - pr_debug_ratelimited("Dropped {multi|broad}cast of type=[%x]\n", - ntohs(skb->protocol)); - kfree_skb(skb); - goto out; - } - /* The ipvlan is a pseudo-L2 device, so the packets that we receive * will have L2; which need to discarded and processed further * in the net-ns of the main-device. */ if (skb_mac_header_was_set(skb)) { + /* In this mode we dont care about + * multicast and broadcast traffic */ + if (is_multicast_ether_addr(ethh->h_dest)) { + pr_debug_ratelimited( + "Dropped {multi|broad}cast of type=[%x]\n", + ntohs(skb->protocol)); + kfree_skb(skb); + goto out; + } + skb_pull(skb, sizeof(*ethh)); skb->mac_header = (typeof(skb->mac_header))~0U; skb_reset_network_header(skb); diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index ba3dfac1d904..b805abc9ec3b 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -164,7 +164,6 @@ static void ipvlan_uninit(struct net_device *dev) static int ipvlan_open(struct net_device *dev) { struct ipvl_dev *ipvlan = netdev_priv(dev); - struct net_device *phy_dev = ipvlan->phy_dev; struct ipvl_addr *addr; if (ipvlan->port->mode == IPVLAN_MODE_L3 || @@ -178,7 +177,7 @@ static int ipvlan_open(struct net_device *dev) ipvlan_ht_addr_add(ipvlan, addr); rcu_read_unlock(); - return dev_uc_add(phy_dev, phy_dev->dev_addr); + return 0; } static int ipvlan_stop(struct net_device *dev) @@ -190,8 +189,6 @@ static int ipvlan_stop(struct net_device *dev) dev_uc_unsync(phy_dev, dev); dev_mc_unsync(phy_dev, dev); - dev_uc_del(phy_dev, phy_dev->dev_addr); - rcu_read_lock(); list_for_each_entry_rcu(addr, &ipvlan->addrs, anode) ipvlan_ht_addr_del(addr); diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index afd8b2a08245..32c627702ac5 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -2882,6 +2883,11 @@ static void macsec_dev_set_rx_mode(struct net_device *dev) dev_uc_sync(real_dev, dev); } +static sci_t dev_to_sci(struct net_device *dev, __be16 port) +{ + return make_sci(dev->dev_addr, port); +} + static int macsec_set_mac_address(struct net_device *dev, void *p) { struct macsec_dev *macsec = macsec_priv(dev); @@ -2903,6 +2909,7 @@ static int macsec_set_mac_address(struct net_device *dev, void *p) out: ether_addr_copy(dev->dev_addr, addr->sa_data); + macsec->secy.sci = dev_to_sci(dev, MACSEC_PORT_ES); return 0; } @@ -2977,6 +2984,7 @@ static const struct device_type macsec_type = { static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = { [IFLA_MACSEC_SCI] = { .type = NLA_U64 }, + [IFLA_MACSEC_PORT] = { .type = NLA_U16 }, [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 }, [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 }, [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 }, @@ -3176,11 +3184,6 @@ static bool sci_exists(struct net_device *dev, sci_t sci) return false; } -static sci_t dev_to_sci(struct net_device *dev, __be16 port) -{ - return make_sci(dev->dev_addr, port); -} - static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len) { struct macsec_dev *macsec = macsec_priv(dev); @@ -3234,6 +3237,8 @@ static int macsec_newlink(struct net *net, struct net_device *dev, real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK])); if (!real_dev) return -ENODEV; + if (real_dev->type != ARPHRD_ETHER) + return -EINVAL; dev->priv_flags |= IFF_MACSEC; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index c5bf61565726..26f6be4796c7 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -334,6 +334,8 @@ static void macvlan_process_broadcast(struct work_struct *w) if (src) dev_put(src->dev); consume_skb(skb); + + cond_resched(); } } diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c index 23f1958ba6ad..459fb2069c7e 100644 --- a/drivers/net/phy/bcm63xx.c +++ b/drivers/net/phy/bcm63xx.c @@ -73,6 +73,7 @@ static struct phy_driver bcm63xx_driver[] = { /* same phy as above, with just a different OUI */ .phy_id = 0x002bdc00, .phy_id_mask = 0xfffffc00, + .name = "Broadcom BCM63XX (2)", /* PHY_BASIC_FEATURES */ .flags = PHY_IS_INTERNAL, .config_init = bcm63xx_config_init, diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 52e80434e45e..31a559513362 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -25,7 +25,8 @@ #define DP83867_CFG3 0x1e /* Extended Registers */ -#define DP83867_CFG4 0x0031 +#define DP83867_FLD_THR_CFG 0x002e +#define DP83867_CFG4 0x0031 #define DP83867_CFG4_SGMII_ANEG_MASK (BIT(5) | BIT(6)) #define DP83867_CFG4_SGMII_ANEG_TIMER_11MS (3 << 5) #define DP83867_CFG4_SGMII_ANEG_TIMER_800US (2 << 5) @@ -74,6 +75,7 @@ #define DP83867_STRAP_STS2_CLK_SKEW_RX_MASK GENMASK(2, 0) #define DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT 0 #define DP83867_STRAP_STS2_CLK_SKEW_NONE BIT(2) +#define DP83867_STRAP_STS2_STRAP_FLD BIT(10) /* PHY CTRL bits */ #define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14 @@ -103,6 +105,9 @@ /* CFG4 bits */ #define DP83867_CFG4_PORT_MIRROR_EN BIT(0) +/* FLD_THR_CFG */ +#define DP83867_FLD_THR_CFG_ENERGY_LOST_THR_MASK 0x7 + enum { DP83867_PORT_MIRROING_KEEP, DP83867_PORT_MIRROING_EN, @@ -318,6 +323,20 @@ static int dp83867_config_init(struct phy_device *phydev) phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, BIT(7)); + bs = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS2); + if (bs & DP83867_STRAP_STS2_STRAP_FLD) { + /* When using strap to enable FLD, the ENERGY_LOST_FLD_THR will + * be set to 0x2. This may causes the PHY link to be unstable - + * the default value 0x1 need to be restored. + */ + ret = phy_modify_mmd(phydev, DP83867_DEVADDR, + DP83867_FLD_THR_CFG, + DP83867_FLD_THR_CFG_ENERGY_LOST_THR_MASK, + 0x1); + if (ret) + return ret; + } + if (phy_interface_is_rgmii(phydev)) { val = phy_read(phydev, MII_DP83867_PHYCTRL); if (val < 0) diff --git a/drivers/net/phy/mdio-bcm-unimac.c b/drivers/net/phy/mdio-bcm-unimac.c index 4a28fb29adaa..fbd36891ee64 100644 --- a/drivers/net/phy/mdio-bcm-unimac.c +++ b/drivers/net/phy/mdio-bcm-unimac.c @@ -242,11 +242,9 @@ static int unimac_mdio_probe(struct platform_device *pdev) return -ENOMEM; } - priv->clk = devm_clk_get(&pdev->dev, NULL); - if (PTR_ERR(priv->clk) == -EPROBE_DEFER) + priv->clk = devm_clk_get_optional(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) return PTR_ERR(priv->clk); - else - priv->clk = NULL; ret = clk_prepare_enable(priv->clk); if (ret) diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index 88d409e48c1f..aad6809ebe39 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -288,8 +288,13 @@ static int mdio_mux_iproc_suspend(struct device *dev) static int mdio_mux_iproc_resume(struct device *dev) { struct iproc_mdiomux_desc *md = dev_get_drvdata(dev); + int rc; - clk_prepare_enable(md->core_clk); + rc = clk_prepare_enable(md->core_clk); + if (rc) { + dev_err(md->dev, "failed to enable core clk\n"); + return rc; + } mdio_mux_iproc_config(md); return 0; diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index 7ada1fd9ca71..2339b9381d21 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -302,11 +302,11 @@ enum rgmii_rx_clock_delay { BIT(VSC8531_FORCE_LED_OFF) | \ BIT(VSC8531_FORCE_LED_ON)) -#define MSCC_VSC8584_REVB_INT8051_FW "mscc_vsc8584_revb_int8051_fb48.bin" +#define MSCC_VSC8584_REVB_INT8051_FW "microchip/mscc_vsc8584_revb_int8051_fb48.bin" #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800 #define MSCC_VSC8584_REVB_INT8051_FW_CRC 0xfb48 -#define MSCC_VSC8574_REVB_INT8051_FW "mscc_vsc8574_revb_int8051_29e8.bin" +#define MSCC_VSC8574_REVB_INT8051_FW "microchip/mscc_vsc8574_revb_int8051_29e8.bin" #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000 #define MSCC_VSC8574_REVB_INT8051_FW_CRC 0x29e8 diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 105d389b58e7..ea890d802ffe 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -761,7 +761,8 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) phy_trigger_machine(phydev); } - if (phy_clear_interrupt(phydev)) + /* did_interrupt() may have cleared the interrupt already */ + if (!phydev->drv->did_interrupt && phy_clear_interrupt(phydev)) goto phy_err; return IRQ_HANDLED; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2bf0fda209a8..0907c3d8d94a 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -246,7 +246,7 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) * MDIO bus driver and clock gated at this point. */ if (!netdev) - return !phydev->suspended; + goto out; if (netdev->wol_enabled) return false; @@ -266,7 +266,8 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) if (device_may_wakeup(&netdev->dev)) return false; - return true; +out: + return !phydev->suspended; } static int mdio_bus_phy_suspend(struct device *dev) @@ -284,6 +285,8 @@ static int mdio_bus_phy_suspend(struct device *dev) if (!mdio_bus_phy_may_suspend(phydev)) return 0; + phydev->suspended_by_mdio_bus = 1; + return phy_suspend(phydev); } @@ -292,9 +295,11 @@ static int mdio_bus_phy_resume(struct device *dev) struct phy_device *phydev = to_phy_device(dev); int ret; - if (!mdio_bus_phy_may_suspend(phydev)) + if (!phydev->suspended_by_mdio_bus) goto no_resume; + phydev->suspended_by_mdio_bus = 0; + ret = phy_resume(phydev); if (ret < 0) return ret; diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index 58a69f830d29..f78ceba42e57 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -232,7 +232,7 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, struct cstate *cs = lcs->next; unsigned long deltaS, deltaA; short changes = 0; - int hlen; + int nlen, hlen; unsigned char new_seq[16]; unsigned char *cp = new_seq; struct iphdr *ip; @@ -248,6 +248,8 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, return isize; ip = (struct iphdr *) icp; + if (ip->version != 4 || ip->ihl < 5) + return isize; /* Bail if this packet isn't TCP, or is an IP fragment */ if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) { @@ -258,10 +260,14 @@ slhc_compress(struct slcompress *comp, unsigned char *icp, int isize, comp->sls_o_tcp++; return isize; } - /* Extract TCP header */ + nlen = ip->ihl * 4; + if (isize < nlen + sizeof(*th)) + return isize; - th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4); - hlen = ip->ihl*4 + th->doff*4; + th = (struct tcphdr *)(icp + nlen); + if (th->doff < sizeof(struct tcphdr) / 4) + return isize; + hlen = nlen + th->doff * 4; /* Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or * some other control bit is set). Also uncompressible if diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 61d7e0d1d77d..8e56a41dd758 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -863,7 +863,10 @@ err_free_chan: tty->disc_data = NULL; clear_bit(SLF_INUSE, &sl->flags); sl_free_netdev(sl->dev); + /* do not call free_netdev before rtnl_unlock */ + rtnl_unlock(); free_netdev(sl->dev); + return err; err_exit: rtnl_unlock(); diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index ca70a1d840eb..4004f98e50d9 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2240,6 +2240,8 @@ team_nl_option_policy[TEAM_ATTR_OPTION_MAX + 1] = { [TEAM_ATTR_OPTION_CHANGED] = { .type = NLA_FLAG }, [TEAM_ATTR_OPTION_TYPE] = { .type = NLA_U8 }, [TEAM_ATTR_OPTION_DATA] = { .type = NLA_BINARY }, + [TEAM_ATTR_OPTION_PORT_IFINDEX] = { .type = NLA_U32 }, + [TEAM_ATTR_OPTION_ARRAY_INDEX] = { .type = NLA_U32 }, }; static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 3b7a3b8a5e06..6c738a271257 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -337,6 +337,9 @@ static void qmi_wwan_netdev_setup(struct net_device *net) netdev_dbg(net, "mode: raw IP\n"); } else if (!net->header_ops) { /* don't bother if already set */ ether_setup(net); + /* Restoring min/max mtu values set originally by usbnet */ + net->min_mtu = 0; + net->max_mtu = ETH_MAX_MTU; clear_bit(EVENT_NO_IP_ALIGN, &dev->flags); netdev_dbg(net, "mode: Ethernet\n"); } @@ -1207,6 +1210,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1435, 0xd182, 5)}, /* Wistron NeWeb D18 */ {QMI_FIXED_INTF(0x1435, 0xd191, 4)}, /* Wistron NeWeb D19Q1 */ {QMI_QUIRK_SET_DTR(0x1508, 0x1001, 4)}, /* Fibocom NL668 series */ + {QMI_FIXED_INTF(0x1690, 0x7588, 4)}, /* ASKEY WWHC050 */ {QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */ {QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */ {QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 6912624eed4a..44ea5dcc43fd 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -3006,6 +3006,8 @@ static u16 r8153_phy_status(struct r8152 *tp, u16 desired) } msleep(20); + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + break; } return data; @@ -4419,7 +4421,10 @@ static void r8153_init(struct r8152 *tp) if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & AUTOLOAD_DONE) break; + msleep(20); + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + break; } data = r8153_phy_status(tp, 0); @@ -4545,7 +4550,10 @@ static void r8153b_init(struct r8152 *tp) if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) & AUTOLOAD_DONE) break; + msleep(20); + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + break; } data = r8153_phy_status(tp, 0); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 283dfeb406ad..93690f77ec9c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2779,10 +2779,19 @@ static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan, /* Setup stats when device is created */ static int vxlan_init(struct net_device *dev) { + struct vxlan_dev *vxlan = netdev_priv(dev); + int err; + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; + err = gro_cells_init(&vxlan->gro_cells, dev); + if (err) { + free_percpu(dev->tstats); + return err; + } + return 0; } @@ -3043,8 +3052,6 @@ static void vxlan_setup(struct net_device *dev) vxlan->dev = dev; - gro_cells_init(&vxlan->gro_cells, dev); - for (h = 0; h < FDB_HASH_SIZE; ++h) { spin_lock_init(&vxlan->hash_lock[h]); INIT_HLIST_HEAD(&vxlan->fdb_head[h]); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index c59cbb8cbdd7..c54fe6650018 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -1181,7 +1181,7 @@ int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) static int iwl_mvm_ppag_init(struct iwl_mvm *mvm) { - return -ENOENT; + return 0; } #endif /* CONFIG_ACPI */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index 945c1ea5cda8..ed367b0a185c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -309,7 +309,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) } /* PHY_SKU section is mandatory in B0 */ - if (!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) { + if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT && + !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) { IWL_ERR(mvm, "Can't parse phy_sku in B0, empty sections\n"); return NULL; diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 8f69d00bd940..6249a46c1976 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -448,10 +448,13 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, struct page *page = virt_to_head_page(data); int offset = data - page_address(page); struct sk_buff *skb = q->rx_head; + struct skb_shared_info *shinfo = skb_shinfo(skb); - offset += q->buf_offset; - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, len, - q->buf_size); + if (shinfo->nr_frags < ARRAY_SIZE(shinfo->frags)) { + offset += q->buf_offset; + skb_add_rx_frag(skb, shinfo->nr_frags, page, offset, len, + q->buf_size); + } if (more) return; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index 917729807514..e17f70b4d199 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -561,6 +561,7 @@ static inline void clear_pci_tx_desc_content(__le32 *__pdesc, int _size) rxmcs == DESC92C_RATE11M) struct phy_status_rpt { + u8 padding[2]; u8 ch_corr[2]; u8 cck_sig_qual_ofdm_pwdb_all; u8 cck_agc_rpt_ofdm_cfosho_a; diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c index 0cc9ac856fe2..ed2123129e0e 100644 --- a/drivers/nfc/fdp/fdp.c +++ b/drivers/nfc/fdp/fdp.c @@ -184,7 +184,7 @@ static int fdp_nci_send_patch(struct nci_dev *ndev, u8 conn_id, u8 type) const struct firmware *fw; struct sk_buff *skb; unsigned long len; - u8 max_size, payload_size; + int max_size, payload_size; int rc = 0; if ((type == NCI_PATCH_TYPE_OTP && !info->otp_patch) || @@ -207,8 +207,7 @@ static int fdp_nci_send_patch(struct nci_dev *ndev, u8 conn_id, u8 type) while (len) { - payload_size = min_t(unsigned long, (unsigned long) max_size, - len); + payload_size = min_t(unsigned long, max_size, len); skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + payload_size), GFP_KERNEL); diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 7dacfd102a99..b8fe42f4b3c5 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1161,8 +1161,8 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl, static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid, unsigned int dword11, void *buffer, size_t buflen, u32 *result) { + union nvme_result res = { 0 }; struct nvme_command c; - union nvme_result res; int ret; memset(&c, 0, sizeof(c)); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 570c75c92e29..cd64ddb129e5 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2753,6 +2753,18 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev) (dmi_match(DMI_BOARD_NAME, "PRIME B350M-A") || dmi_match(DMI_BOARD_NAME, "PRIME Z370-A"))) return NVME_QUIRK_NO_APST; + } else if ((pdev->vendor == 0x144d && (pdev->device == 0xa801 || + pdev->device == 0xa808 || pdev->device == 0xa809)) || + (pdev->vendor == 0x1e0f && pdev->device == 0x0001)) { + /* + * Forcing to use host managed nvme power settings for + * lowest idle power with quick resume latency on + * Samsung and Toshiba SSDs based on suspend behavior + * on Coffee Lake board for LENOVO C640 + */ + if ((dmi_match(DMI_BOARD_VENDOR, "LENOVO")) && + dmi_match(DMI_BOARD_NAME, "LNVNB161216")) + return NVME_QUIRK_SIMPLE_SUSPEND; } return 0; @@ -3114,7 +3126,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_NO_DEEPEST_PS | NVME_QUIRK_IGNORE_DEV_SUBNQN, }, { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, - { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) }, + { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001), + .driver_data = NVME_QUIRK_SINGLE_VECTOR }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005), .driver_data = NVME_QUIRK_SINGLE_VECTOR | diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index d535080b781f..2fe34fd4c3f3 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -515,7 +515,7 @@ static int nvmet_try_send_data_pdu(struct nvmet_tcp_cmd *cmd) return 1; } -static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd) +static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd, bool last_in_batch) { struct nvmet_tcp_queue *queue = cmd->queue; int ret; @@ -523,9 +523,15 @@ static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd) while (cmd->cur_sg) { struct page *page = sg_page(cmd->cur_sg); u32 left = cmd->cur_sg->length - cmd->offset; + int flags = MSG_DONTWAIT; + + if ((!last_in_batch && cmd->queue->send_list_len) || + cmd->wbytes_done + left < cmd->req.transfer_len || + queue->data_digest || !queue->nvme_sq.sqhd_disabled) + flags |= MSG_MORE; ret = kernel_sendpage(cmd->queue->sock, page, cmd->offset, - left, MSG_DONTWAIT | MSG_MORE); + left, flags); if (ret <= 0) return ret; @@ -660,7 +666,7 @@ static int nvmet_tcp_try_send_one(struct nvmet_tcp_queue *queue, } if (cmd->state == NVMET_TCP_SEND_DATA) { - ret = nvmet_try_send_data(cmd); + ret = nvmet_try_send_data(cmd, last_in_batch); if (ret <= 0) goto done_send; } diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index bd6129db6417..c34a6df712ad 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -268,6 +268,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) rc = of_mdiobus_register_phy(mdio, child, addr); if (rc && rc != -ENODEV) goto unregister; + break; } } } diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c index acce8781c456..f5c7a845cd7b 100644 --- a/drivers/perf/arm_pmu_acpi.c +++ b/drivers/perf/arm_pmu_acpi.c @@ -24,8 +24,6 @@ static int arm_pmu_acpi_register_irq(int cpu) int gsi, trigger; gicc = acpi_cpu_get_madt_gicc(cpu); - if (WARN_ON(!gicc)) - return -EINVAL; gsi = gicc->performance_interrupt; @@ -64,11 +62,10 @@ static void arm_pmu_acpi_unregister_irq(int cpu) int gsi; gicc = acpi_cpu_get_madt_gicc(cpu); - if (!gicc) - return; gsi = gicc->performance_interrupt; - acpi_unregister_gsi(gsi); + if (gsi) + acpi_unregister_gsi(gsi); } #if IS_ENABLED(CONFIG_ARM_SPE_PMU) diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c index 0e51baa48b14..6eef47de8fcc 100644 --- a/drivers/perf/fsl_imx8_ddr_perf.c +++ b/drivers/perf/fsl_imx8_ddr_perf.c @@ -327,9 +327,10 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config, if (enable) { /* - * must disable first, then enable again - * otherwise, cycle counter will not work - * if previous state is enabled. + * cycle counter is special which should firstly write 0 then + * write 1 into CLEAR bit to clear it. Other counters only + * need write 0 into CLEAR bit and it turns out to be 1 by + * hardware. Below enable flow is harmless for all counters. */ writel(0, pmu->base + reg); val = CNTL_EN | CNTL_CLEAR; @@ -337,7 +338,8 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config, writel(val, pmu->base + reg); } else { /* Disable counter */ - writel(0, pmu->base + reg); + val = readl_relaxed(pmu->base + reg) & CNTL_EN_MASK; + writel(val, pmu->base + reg); } } diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c index f20524f0c21d..94a34cf75eb3 100644 --- a/drivers/phy/motorola/phy-mapphone-mdm6600.c +++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c @@ -20,6 +20,7 @@ #define PHY_MDM6600_PHY_DELAY_MS 4000 /* PHY enable 2.2s to 3.5s */ #define PHY_MDM6600_ENABLED_DELAY_MS 8000 /* 8s more total for MDM6600 */ +#define PHY_MDM6600_WAKE_KICK_MS 600 /* time on after GPIO toggle */ #define MDM6600_MODEM_IDLE_DELAY_MS 1000 /* modem after USB suspend */ #define MDM6600_MODEM_WAKE_DELAY_MS 200 /* modem response after idle */ @@ -243,10 +244,24 @@ static irqreturn_t phy_mdm6600_wakeirq_thread(int irq, void *data) { struct phy_mdm6600 *ddata = data; struct gpio_desc *mode_gpio1; + int error, wakeup; mode_gpio1 = ddata->mode_gpios->desc[PHY_MDM6600_MODE1]; - dev_dbg(ddata->dev, "OOB wake on mode_gpio1: %i\n", - gpiod_get_value(mode_gpio1)); + wakeup = gpiod_get_value(mode_gpio1); + if (!wakeup) + return IRQ_NONE; + + dev_dbg(ddata->dev, "OOB wake on mode_gpio1: %i\n", wakeup); + error = pm_runtime_get_sync(ddata->dev); + if (error < 0) { + pm_runtime_put_noidle(ddata->dev); + + return IRQ_NONE; + } + + /* Just wake-up and kick the autosuspend timer */ + pm_runtime_mark_last_busy(ddata->dev); + pm_runtime_put_autosuspend(ddata->dev); return IRQ_HANDLED; } @@ -496,8 +511,14 @@ static void phy_mdm6600_modem_wake(struct work_struct *work) ddata = container_of(work, struct phy_mdm6600, modem_wake_work.work); phy_mdm6600_wake_modem(ddata); + + /* + * The modem does not always stay awake 1.2 seconds after toggling + * the wake GPIO, and sometimes it idles after about some 600 ms + * making writes time out. + */ schedule_delayed_work(&ddata->modem_wake_work, - msecs_to_jiffies(MDM6600_MODEM_IDLE_DELAY_MS)); + msecs_to_jiffies(PHY_MDM6600_WAKE_KICK_MS)); } static int __maybe_unused phy_mdm6600_runtime_suspend(struct device *dev) diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c index a28bd15297f5..1c536fc03c83 100644 --- a/drivers/phy/ti/phy-gmii-sel.c +++ b/drivers/phy/ti/phy-gmii-sel.c @@ -80,20 +80,20 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode) break; case PHY_INTERFACE_MODE_MII: - mode = AM33XX_GMII_SEL_MODE_MII; + case PHY_INTERFACE_MODE_GMII: + gmii_sel_mode = AM33XX_GMII_SEL_MODE_MII; break; default: - dev_warn(dev, - "port%u: unsupported mode: \"%s\". Defaulting to MII.\n", - if_phy->id, phy_modes(rgmii_id)); + dev_warn(dev, "port%u: unsupported mode: \"%s\"\n", + if_phy->id, phy_modes(submode)); return -EINVAL; } if_phy->phy_if_mode = submode; dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n", - __func__, if_phy->id, mode, rgmii_id, + __func__, if_phy->id, submode, rgmii_id, if_phy->rmii_clock_external); regfield = if_phy->fields[PHY_GMII_SEL_PORT_MODE]; diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 2bbd8ee93507..b4ef9b6c65ac 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -176,6 +176,7 @@ const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin) return desc->name; } +EXPORT_SYMBOL_GPL(pin_get_name); /* Deletes a range of pin descriptors */ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev, @@ -2025,7 +2026,6 @@ static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev) return PTR_ERR(pctldev->p); } - kref_get(&pctldev->p->users); pctldev->hog_default = pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT); if (IS_ERR(pctldev->hog_default)) { diff --git a/drivers/pinctrl/freescale/pinctrl-scu.c b/drivers/pinctrl/freescale/pinctrl-scu.c index 73bf1d9f9cc6..23cf04bdfc55 100644 --- a/drivers/pinctrl/freescale/pinctrl-scu.c +++ b/drivers/pinctrl/freescale/pinctrl-scu.c @@ -23,12 +23,12 @@ struct imx_sc_msg_req_pad_set { struct imx_sc_rpc_msg hdr; u32 val; u16 pad; -} __packed; +} __packed __aligned(4); struct imx_sc_msg_req_pad_get { struct imx_sc_rpc_msg hdr; u16 pad; -} __packed; +} __packed __aligned(4); struct imx_sc_msg_resp_pad_get { struct imx_sc_rpc_msg hdr; diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c index 72c5373c8dc1..e8d1f3050487 100644 --- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c +++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c @@ -147,8 +147,8 @@ static const unsigned int sdio_d0_pins[] = { GPIOX_0 }; static const unsigned int sdio_d1_pins[] = { GPIOX_1 }; static const unsigned int sdio_d2_pins[] = { GPIOX_2 }; static const unsigned int sdio_d3_pins[] = { GPIOX_3 }; -static const unsigned int sdio_cmd_pins[] = { GPIOX_4 }; -static const unsigned int sdio_clk_pins[] = { GPIOX_5 }; +static const unsigned int sdio_clk_pins[] = { GPIOX_4 }; +static const unsigned int sdio_cmd_pins[] = { GPIOX_5 }; static const unsigned int sdio_irq_pins[] = { GPIOX_7 }; static const unsigned int nand_ce0_pins[] = { BOOT_8 }; diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 9eb86309c70b..dfef471201f6 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -286,6 +286,7 @@ out: kfree(cfg); return ret; } +EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_config); int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **map, diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c index a454f57c264e..62c02b969327 100644 --- a/drivers/pinctrl/pinctrl-falcon.c +++ b/drivers/pinctrl/pinctrl-falcon.c @@ -451,7 +451,7 @@ static int pinctrl_falcon_probe(struct platform_device *pdev) falcon_info.clk[*bank] = clk_get(&ppdev->dev, NULL); if (IS_ERR(falcon_info.clk[*bank])) { dev_err(&ppdev->dev, "failed to get clock\n"); - of_node_put(np) + of_node_put(np); return PTR_ERR(falcon_info.clk[*bank]); } falcon_info.membase[*bank] = devm_ioremap_resource(&pdev->dev, diff --git a/drivers/pinctrl/sprd/Kconfig b/drivers/pinctrl/sprd/Kconfig index b6c5479b58fb..eef35d01b770 100644 --- a/drivers/pinctrl/sprd/Kconfig +++ b/drivers/pinctrl/sprd/Kconfig @@ -4,9 +4,7 @@ # config PINCTRL_SPRD - bool "Spreadtrum pinctrl driver" - depends on OF - depends on ARCH_SPRD || COMPILE_TEST + tristate select PINMUX select PINCONF select GENERIC_PINCONF @@ -15,7 +13,9 @@ config PINCTRL_SPRD Say Y here to enable Spreadtrum pinctrl driver config PINCTRL_SPRD_SC9860 - bool "Spreadtrum SC9860 pinctrl driver" - depends on PINCTRL_SPRD + tristate "Spreadtrum SC9860 pinctrl driver" + depends on OF + depends on ARCH_SPRD || COMPILE_TEST + select PINCTRL_SPRD help Say Y here to enable Spreadtrum SC9860 pinctrl driver diff --git a/drivers/pinctrl/sprd/pinctrl-sprd.c b/drivers/pinctrl/sprd/pinctrl-sprd.c index 157712ab05a8..ea04bac3b453 100644 --- a/drivers/pinctrl/sprd/pinctrl-sprd.c +++ b/drivers/pinctrl/sprd/pinctrl-sprd.c @@ -1090,6 +1090,7 @@ int sprd_pinctrl_core_probe(struct platform_device *pdev, return 0; } +EXPORT_SYMBOL_GPL(sprd_pinctrl_core_probe); int sprd_pinctrl_remove(struct platform_device *pdev) { @@ -1098,6 +1099,7 @@ int sprd_pinctrl_remove(struct platform_device *pdev) pinctrl_unregister(sprd_pctl->pctl); return 0; } +EXPORT_SYMBOL_GPL(sprd_pinctrl_remove); void sprd_pinctrl_shutdown(struct platform_device *pdev) { @@ -1112,6 +1114,7 @@ void sprd_pinctrl_shutdown(struct platform_device *pdev) return; pinctrl_select_state(pinctl, state); } +EXPORT_SYMBOL_GPL(sprd_pinctrl_shutdown); MODULE_DESCRIPTION("SPREADTRUM Pin Controller Driver"); MODULE_AUTHOR("Baolin Wang "); diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c index 52ef1419b671..2b1a3a6ee8db 100644 --- a/drivers/platform/x86/pmc_atom.c +++ b/drivers/platform/x86/pmc_atom.c @@ -383,6 +383,14 @@ static const struct dmi_system_id critclk_systems[] = { DMI_MATCH(DMI_PRODUCT_NAME, "3I380D"), }, }, + { + /* pmc_plt_clk* - are used for ethernet controllers */ + .ident = "Lex 2I385SW", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Lex BayTrail"), + DMI_MATCH(DMI_PRODUCT_NAME, "2I385SW"), + }, + }, { /* pmc_plt_clk* - are used for ethernet controllers */ .ident = "Beckhoff CB3163", diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 92a239e212df..da5c5aad3a68 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -238,7 +238,7 @@ config SYSCON_REBOOT_MODE action according to the mode. config POWER_RESET_SC27XX - bool "Spreadtrum SC27xx PMIC power-off driver" + tristate "Spreadtrum SC27xx PMIC power-off driver" depends on MFD_SC27XX_PMIC || COMPILE_TEST help This driver supports powering off a system through diff --git a/drivers/power/reset/sc27xx-poweroff.c b/drivers/power/reset/sc27xx-poweroff.c index 29fb08b8faa0..69863074daf6 100644 --- a/drivers/power/reset/sc27xx-poweroff.c +++ b/drivers/power/reset/sc27xx-poweroff.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -13,6 +14,8 @@ #define SC27XX_PWR_PD_HW 0xc2c #define SC27XX_PWR_OFF_EN BIT(0) +#define SC27XX_SLP_CTRL 0xdf0 +#define SC27XX_LDO_XTL_EN BIT(3) static struct regmap *regmap; @@ -27,10 +30,13 @@ static struct regmap *regmap; */ static void sc27xx_poweroff_shutdown(void) { -#ifdef CONFIG_PM_SLEEP_SMP - int cpu = smp_processor_id(); +#ifdef CONFIG_HOTPLUG_CPU + int cpu; - freeze_secondary_cpus(cpu); + for_each_online_cpu(cpu) { + if (cpu != smp_processor_id()) + cpu_down(cpu); + } #endif } @@ -40,6 +46,9 @@ static struct syscore_ops poweroff_syscore_ops = { static void sc27xx_poweroff_do_poweroff(void) { + /* Disable the external subsys connection's power firstly */ + regmap_write(regmap, SC27XX_SLP_CTRL, SC27XX_LDO_XTL_EN); + regmap_write(regmap, SC27XX_PWR_PD_HW, SC27XX_PWR_OFF_EN); } @@ -63,4 +72,8 @@ static struct platform_driver sc27xx_poweroff_driver = { .name = "sc27xx-poweroff", }, }; -builtin_platform_driver(sc27xx_poweroff_driver); +module_platform_driver(sc27xx_poweroff_driver); + +MODULE_DESCRIPTION("Power off driver for SC27XX PMIC Device"); +MODULE_AUTHOR("Baolin Wang "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 7d6adf5eb4af..57d3c1a16ca1 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -493,7 +493,7 @@ config CHARGER_GPIO called gpio-charger. config CHARGER_MANAGER - bool "Battery charger manager for multiple chargers" + tristate "Battery charger manager for multiple chargers" depends on REGULATOR select EXTCON help diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index d079f82a6b64..f3319567d570 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -569,9 +569,11 @@ EXPORT_SYMBOL_GPL(devm_power_supply_get_by_phandle); int power_supply_get_battery_info(struct power_supply *psy, struct power_supply_battery_info *info) { + struct power_supply_resistance_temp_table *resist_table; struct device_node *battery_np; const char *value; int err, len, index; + const __be32 *list; info->energy_full_design_uwh = -EINVAL; info->charge_full_design_uah = -EINVAL; @@ -582,6 +584,7 @@ int power_supply_get_battery_info(struct power_supply *psy, info->constant_charge_current_max_ua = -EINVAL; info->constant_charge_voltage_max_uv = -EINVAL; info->factory_internal_resistance_uohm = -EINVAL; + info->resist_table = NULL; for (index = 0; index < POWER_SUPPLY_OCV_TEMP_MAX; index++) { info->ocv_table[index] = NULL; @@ -648,7 +651,6 @@ int power_supply_get_battery_info(struct power_supply *psy, for (index = 0; index < len; index++) { struct power_supply_battery_ocv_table *table; char *propname; - const __be32 *list; int i, tab_len, size; propname = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d", index); @@ -681,6 +683,26 @@ int power_supply_get_battery_info(struct power_supply *psy, } } + list = of_get_property(battery_np, "resistance-temp-table", &len); + if (!list || !len) + goto out_put_node; + + info->resist_table_size = len / (2 * sizeof(__be32)); + resist_table = info->resist_table = devm_kcalloc(&psy->dev, + info->resist_table_size, + sizeof(*resist_table), + GFP_KERNEL); + if (!info->resist_table) { + power_supply_put_battery_info(psy, info); + err = -ENOMEM; + goto out_put_node; + } + + for (index = 0; index < info->resist_table_size; index++) { + resist_table[index].temp = be32_to_cpu(*list++); + resist_table[index].resistance = be32_to_cpu(*list++); + } + out_put_node: of_node_put(battery_np); return err; @@ -696,9 +718,52 @@ void power_supply_put_battery_info(struct power_supply *psy, if (info->ocv_table[i]) devm_kfree(&psy->dev, info->ocv_table[i]); } + + if (info->resist_table) + devm_kfree(&psy->dev, info->resist_table); } EXPORT_SYMBOL_GPL(power_supply_put_battery_info); +/** + * power_supply_temp2resist_simple() - find the battery internal resistance + * percent + * @table: Pointer to battery resistance temperature table + * @table_len: The table length + * @ocv: Current temperature + * + * This helper function is used to look up battery internal resistance percent + * according to current temperature value from the resistance temperature table, + * and the table must be ordered descending. Then the actual battery internal + * resistance = the ideal battery internal resistance * percent / 100. + * + * Return: the battery internal resistance percent + */ +int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table, + int table_len, int temp) +{ + int i, resist; + + for (i = 0; i < table_len; i++) + if (temp > table[i].temp) + break; + + if (i > 0 && i < table_len) { + int tmp; + + tmp = (table[i - 1].resistance - table[i].resistance) * + (temp - table[i].temp); + tmp /= table[i - 1].temp - table[i].temp; + resist = tmp + table[i].resistance; + } else if (i == 0) { + resist = table[0].resistance; + } else { + resist = table[table_len - 1].resistance; + } + + return resist; +} +EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple); + /** * power_supply_ocv2cap_simple() - find the battery capacity * @table: Pointer to battery OCV lookup table diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index bc8f5bda5762..a7c8a8453db1 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -62,6 +62,8 @@ #define SC27XX_FGU_CUR_BASIC_ADC 8192 #define SC27XX_FGU_SAMPLE_HZ 2 +/* micro Ohms */ +#define SC27XX_FGU_IDEAL_RESISTANCE 20000 /* * struct sc27xx_fgu_data: describe the FGU device @@ -81,9 +83,12 @@ * @max_volt: the maximum constant input voltage in millivolt * @min_volt: the minimum drained battery voltage in microvolt * @table_len: the capacity table length + * @resist_table_len: the resistance table length * @cur_1000ma_adc: ADC value corresponding to 1000 mA * @vol_1000mv_adc: ADC value corresponding to 1000 mV + * @calib_resist: the real resistance of coulomb counter chip in uOhm * @cap_table: capacity table with corresponding ocv + * @resist_table: resistance percent table with corresponding temperature */ struct sc27xx_fgu_data { struct regmap *regmap; @@ -103,15 +108,19 @@ struct sc27xx_fgu_data { int max_volt; int min_volt; int table_len; + int resist_table_len; int cur_1000ma_adc; int vol_1000mv_adc; + int calib_resist; struct power_supply_battery_ocv_table *cap_table; + struct power_supply_resistance_temp_table *resist_table; }; static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity); static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data, int cap, bool int_mode); static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap); +static int sc27xx_fgu_get_temp(struct sc27xx_fgu_data *data, int *temp); static const char * const sc27xx_charger_supply_name[] = { "sc2731_charger", @@ -434,7 +443,7 @@ static int sc27xx_fgu_get_current(struct sc27xx_fgu_data *data, int *val) static int sc27xx_fgu_get_vbat_ocv(struct sc27xx_fgu_data *data, int *val) { - int vol, cur, ret; + int vol, cur, ret, temp, resistance; ret = sc27xx_fgu_get_vbat_vol(data, &vol); if (ret) @@ -444,8 +453,19 @@ static int sc27xx_fgu_get_vbat_ocv(struct sc27xx_fgu_data *data, int *val) if (ret) return ret; + resistance = data->internal_resist; + if (data->resist_table_len > 0) { + ret = sc27xx_fgu_get_temp(data, &temp); + if (ret) + return ret; + + resistance = power_supply_temp2resist_simple(data->resist_table, + data->resist_table_len, temp); + resistance = data->internal_resist * resistance / 100; + } + /* Return the battery OCV in micro volts. */ - *val = vol * 1000 - cur * data->internal_resist; + *val = vol * 1000 - cur * resistance; return 0; } @@ -594,6 +614,17 @@ static int sc27xx_fgu_get_property(struct power_supply *psy, val->intval = data->total_cap * 1000; break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + ret = sc27xx_fgu_get_clbcnt(data, &value); + if (ret) + goto error; + + value = DIV_ROUND_CLOSEST(value * 10, + 36 * SC27XX_FGU_SAMPLE_HZ); + val->intval = sc27xx_fgu_adc_to_current(data, value); + + break; + default: ret = -EINVAL; break; @@ -662,6 +693,7 @@ static enum power_supply_property sc27xx_fgu_props[] = { POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_CALIBRATE, + POWER_SUPPLY_PROP_CHARGE_NOW }; static const struct power_supply_desc sc27xx_fgu_desc = { @@ -884,7 +916,9 @@ static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data) */ cal_4200mv = (calib_data & 0x1ff) + 6963 - 4096 - 256; data->vol_1000mv_adc = DIV_ROUND_CLOSEST(cal_4200mv * 10, 42); - data->cur_1000ma_adc = data->vol_1000mv_adc * 4; + data->cur_1000ma_adc = + DIV_ROUND_CLOSEST(data->vol_1000mv_adc * 4 * data->calib_resist, + SC27XX_FGU_IDEAL_RESISTANCE); kfree(buf); return 0; @@ -929,6 +963,18 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data) if (!data->alarm_cap) data->alarm_cap += 1; + data->resist_table_len = info.resist_table_size; + if (data->resist_table_len > 0) { + data->resist_table = devm_kmemdup(data->dev, info.resist_table, + data->resist_table_len * + sizeof(struct power_supply_resistance_temp_table), + GFP_KERNEL); + if (!data->resist_table) { + power_supply_put_battery_info(data->battery, &info); + return -ENOMEM; + } + } + power_supply_put_battery_info(data->battery, &info); ret = sc27xx_fgu_calibration(data); @@ -1051,6 +1097,15 @@ static int sc27xx_fgu_probe(struct platform_device *pdev) return ret; } + ret = device_property_read_u32(&pdev->dev, + "sprd,calib-resistance-micro-ohms", + &data->calib_resist); + if (ret) { + dev_err(&pdev->dev, + "failed to get fgu calibration resistance\n"); + return ret; + } + data->channel = devm_iio_channel_get(dev, "bat-temp"); if (IS_ERR(data->channel)) { dev_err(dev, "failed to get IIO channel\n"); diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c index 8919a5130bec..25f24df9aa82 100644 --- a/drivers/regulator/stm32-vrefbuf.c +++ b/drivers/regulator/stm32-vrefbuf.c @@ -88,7 +88,7 @@ static int stm32_vrefbuf_disable(struct regulator_dev *rdev) } val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); - val = (val & ~STM32_ENVR) | STM32_HIZ; + val &= ~STM32_ENVR; writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); pm_runtime_mark_last_busy(priv->dev); @@ -175,6 +175,7 @@ static const struct regulator_desc stm32_vrefbuf_regu = { .volt_table = stm32_vrefbuf_voltages, .n_voltages = ARRAY_SIZE(stm32_vrefbuf_voltages), .ops = &stm32_vrefbuf_volt_ops, + .off_on_delay = 1000, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, }; diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5d502fbd5803..c5b980414086 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -327,6 +327,7 @@ config RTC_DRV_MAX6900 config RTC_DRV_MAX8907 tristate "Maxim MAX8907" depends on MFD_MAX8907 || COMPILE_TEST + select REGMAP_IRQ help If you say yes here you will get support for the RTC of Maxim MAX8907 PMIC. diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 6cca72782af6..cf87eb27879f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -178,6 +178,8 @@ struct dasd_block *dasd_alloc_block(void) (unsigned long) block); INIT_LIST_HEAD(&block->ccw_queue); spin_lock_init(&block->queue_lock); + INIT_LIST_HEAD(&block->format_list); + spin_lock_init(&block->format_lock); timer_setup(&block->timer, dasd_block_timeout, 0); spin_lock_init(&block->profile.lock); @@ -1779,20 +1781,26 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, if (dasd_ese_needs_format(cqr->block, irb)) { if (rq_data_dir((struct request *)cqr->callback_data) == READ) { - device->discipline->ese_read(cqr); + device->discipline->ese_read(cqr, irb); cqr->status = DASD_CQR_SUCCESS; cqr->stopclk = now; dasd_device_clear_timer(device); dasd_schedule_device_bh(device); return; } - fcqr = device->discipline->ese_format(device, cqr); + fcqr = device->discipline->ese_format(device, cqr, irb); if (IS_ERR(fcqr)) { + if (PTR_ERR(fcqr) == -EINVAL) { + cqr->status = DASD_CQR_ERROR; + return; + } /* * If we can't format now, let the request go * one extra round. Maybe we can format later. */ cqr->status = DASD_CQR_QUEUED; + dasd_schedule_device_bh(device); + return; } else { fcqr->status = DASD_CQR_QUEUED; cqr->status = DASD_CQR_QUEUED; @@ -2748,11 +2756,13 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr) { struct request *req; blk_status_t error = BLK_STS_OK; + unsigned int proc_bytes; int status; req = (struct request *) cqr->callback_data; dasd_profile_end(cqr->block, cqr, req); + proc_bytes = cqr->proc_bytes; status = cqr->block->base->discipline->free_cp(cqr, req); if (status < 0) error = errno_to_blk_status(status); @@ -2783,7 +2793,18 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr) blk_mq_end_request(req, error); blk_mq_run_hw_queues(req->q, true); } else { - blk_mq_complete_request(req); + /* + * Partial completed requests can happen with ESE devices. + * During read we might have gotten a NRF error and have to + * complete a request partially. + */ + if (proc_bytes) { + blk_update_request(req, BLK_STS_OK, + blk_rq_bytes(req) - proc_bytes); + blk_mq_requeue_request(req, true); + } else { + blk_mq_complete_request(req); + } } } diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index a28b9ff82378..ad44d22e8859 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -207,6 +207,45 @@ static void set_ch_t(struct ch_t *geo, __u32 cyl, __u8 head) geo->head |= head; } +/* + * calculate failing track from sense data depending if + * it is an EAV device or not + */ +static int dasd_eckd_track_from_irb(struct irb *irb, struct dasd_device *device, + sector_t *track) +{ + struct dasd_eckd_private *private = device->private; + u8 *sense = NULL; + u32 cyl; + u8 head; + + sense = dasd_get_sense(irb); + if (!sense) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "ESE error no sense data\n"); + return -EINVAL; + } + if (!(sense[27] & DASD_SENSE_BIT_2)) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "ESE error no valid track data\n"); + return -EINVAL; + } + + if (sense[27] & DASD_SENSE_BIT_3) { + /* enhanced addressing */ + cyl = sense[30] << 20; + cyl |= (sense[31] & 0xF0) << 12; + cyl |= sense[28] << 8; + cyl |= sense[29]; + } else { + cyl = sense[29] << 8; + cyl |= sense[30]; + } + head = sense[31] & 0x0F; + *track = cyl * private->rdc_data.trk_per_cyl + head; + return 0; +} + static int set_timestamp(struct ccw1 *ccw, struct DE_eckd_data *data, struct dasd_device *device) { @@ -2986,6 +3025,37 @@ static int dasd_eckd_format_device(struct dasd_device *base, 0, NULL); } +static bool test_and_set_format_track(struct dasd_format_entry *to_format, + struct dasd_block *block) +{ + struct dasd_format_entry *format; + unsigned long flags; + bool rc = false; + + spin_lock_irqsave(&block->format_lock, flags); + list_for_each_entry(format, &block->format_list, list) { + if (format->track == to_format->track) { + rc = true; + goto out; + } + } + list_add_tail(&to_format->list, &block->format_list); + +out: + spin_unlock_irqrestore(&block->format_lock, flags); + return rc; +} + +static void clear_format_track(struct dasd_format_entry *format, + struct dasd_block *block) +{ + unsigned long flags; + + spin_lock_irqsave(&block->format_lock, flags); + list_del_init(&format->list); + spin_unlock_irqrestore(&block->format_lock, flags); +} + /* * Callback function to free ESE format requests. */ @@ -2993,15 +3063,19 @@ static void dasd_eckd_ese_format_cb(struct dasd_ccw_req *cqr, void *data) { struct dasd_device *device = cqr->startdev; struct dasd_eckd_private *private = device->private; + struct dasd_format_entry *format = data; + clear_format_track(format, cqr->basedev->block); private->count--; dasd_ffree_request(cqr, device); } static struct dasd_ccw_req * -dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr) +dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr, + struct irb *irb) { struct dasd_eckd_private *private; + struct dasd_format_entry *format; struct format_data_t fdata; unsigned int recs_per_trk; struct dasd_ccw_req *fcqr; @@ -3011,23 +3085,39 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr) struct request *req; sector_t first_trk; sector_t last_trk; + sector_t curr_trk; int rc; req = cqr->callback_data; - base = cqr->block->base; + block = cqr->block; + base = block->base; private = base->private; - block = base->block; blksize = block->bp_block; recs_per_trk = recs_per_track(&private->rdc_data, 0, blksize); + format = &startdev->format_entry; first_trk = blk_rq_pos(req) >> block->s2b_shift; sector_div(first_trk, recs_per_trk); last_trk = (blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift; sector_div(last_trk, recs_per_trk); + rc = dasd_eckd_track_from_irb(irb, base, &curr_trk); + if (rc) + return ERR_PTR(rc); - fdata.start_unit = first_trk; - fdata.stop_unit = last_trk; + if (curr_trk < first_trk || curr_trk > last_trk) { + DBF_DEV_EVENT(DBF_WARNING, startdev, + "ESE error track %llu not within range %llu - %llu\n", + curr_trk, first_trk, last_trk); + return ERR_PTR(-EINVAL); + } + format->track = curr_trk; + /* test if track is already in formatting by another thread */ + if (test_and_set_format_track(format, block)) + return ERR_PTR(-EEXIST); + + fdata.start_unit = curr_trk; + fdata.stop_unit = curr_trk; fdata.blksize = blksize; fdata.intensity = private->uses_cdl ? DASD_FMT_INT_COMPAT : 0; @@ -3044,6 +3134,7 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr) return fcqr; fcqr->callback = dasd_eckd_ese_format_cb; + fcqr->callback_data = (void *) format; return fcqr; } @@ -3051,29 +3142,87 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr) /* * When data is read from an unformatted area of an ESE volume, this function * returns zeroed data and thereby mimics a read of zero data. + * + * The first unformatted track is the one that got the NRF error, the address is + * encoded in the sense data. + * + * All tracks before have returned valid data and should not be touched. + * All tracks after the unformatted track might be formatted or not. This is + * currently not known, remember the processed data and return the remainder of + * the request to the blocklayer in __dasd_cleanup_cqr(). */ -static void dasd_eckd_ese_read(struct dasd_ccw_req *cqr) +static int dasd_eckd_ese_read(struct dasd_ccw_req *cqr, struct irb *irb) { + struct dasd_eckd_private *private; + sector_t first_trk, last_trk; + sector_t first_blk, last_blk; unsigned int blksize, off; + unsigned int recs_per_trk; struct dasd_device *base; struct req_iterator iter; + struct dasd_block *block; + unsigned int skip_block; + unsigned int blk_count; struct request *req; struct bio_vec bv; + sector_t curr_trk; + sector_t end_blk; char *dst; + int rc; req = (struct request *) cqr->callback_data; base = cqr->block->base; blksize = base->block->bp_block; + block = cqr->block; + private = base->private; + skip_block = 0; + blk_count = 0; + + recs_per_trk = recs_per_track(&private->rdc_data, 0, blksize); + first_trk = first_blk = blk_rq_pos(req) >> block->s2b_shift; + sector_div(first_trk, recs_per_trk); + last_trk = last_blk = + (blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift; + sector_div(last_trk, recs_per_trk); + rc = dasd_eckd_track_from_irb(irb, base, &curr_trk); + if (rc) + return rc; + + /* sanity check if the current track from sense data is valid */ + if (curr_trk < first_trk || curr_trk > last_trk) { + DBF_DEV_EVENT(DBF_WARNING, base, + "ESE error track %llu not within range %llu - %llu\n", + curr_trk, first_trk, last_trk); + return -EINVAL; + } + + /* + * if not the first track got the NRF error we have to skip over valid + * blocks + */ + if (curr_trk != first_trk) + skip_block = curr_trk * recs_per_trk - first_blk; + + /* we have no information beyond the current track */ + end_blk = (curr_trk + 1) * recs_per_trk; rq_for_each_segment(bv, req, iter) { dst = page_address(bv.bv_page) + bv.bv_offset; for (off = 0; off < bv.bv_len; off += blksize) { - if (dst && rq_data_dir(req) == READ) { + if (first_blk + blk_count >= end_blk) { + cqr->proc_bytes = blk_count * blksize; + return 0; + } + if (dst && !skip_block) { dst += off; memset(dst, 0, blksize); + } else { + skip_block--; } + blk_count++; } } + return 0; } /* diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 91c9f9586e0f..fa552f9f1666 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -187,6 +187,7 @@ struct dasd_ccw_req { void (*callback)(struct dasd_ccw_req *, void *data); void *callback_data; + unsigned int proc_bytes; /* bytes for partial completion */ }; /* @@ -387,8 +388,9 @@ struct dasd_discipline { int (*ext_pool_warn_thrshld)(struct dasd_device *); int (*ext_pool_oos)(struct dasd_device *); int (*ext_pool_exhaust)(struct dasd_device *, struct dasd_ccw_req *); - struct dasd_ccw_req *(*ese_format)(struct dasd_device *, struct dasd_ccw_req *); - void (*ese_read)(struct dasd_ccw_req *); + struct dasd_ccw_req *(*ese_format)(struct dasd_device *, + struct dasd_ccw_req *, struct irb *); + int (*ese_read)(struct dasd_ccw_req *, struct irb *); }; extern struct dasd_discipline *dasd_diag_discipline_pointer; @@ -474,6 +476,11 @@ struct dasd_profile { spinlock_t lock; }; +struct dasd_format_entry { + struct list_head list; + sector_t track; +}; + struct dasd_device { /* Block device stuff. */ struct dasd_block *block; @@ -539,6 +546,7 @@ struct dasd_device { struct dentry *debugfs_dentry; struct dentry *hosts_dentry; struct dasd_profile profile; + struct dasd_format_entry format_entry; }; struct dasd_block { @@ -564,6 +572,9 @@ struct dasd_block { struct dentry *debugfs_dentry; struct dasd_profile profile; + + struct list_head format_list; + spinlock_t format_lock; }; struct dasd_attention_data { diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 2a3f874a21d5..9cebff8e8d74 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -303,8 +303,10 @@ static void * cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset) { struct ccwdev_iter *iter; + loff_t p = *offset; - if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1)) + (*offset)++; + if (p >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1)) return NULL; iter = it; if (iter->devno == __MAX_SUBCHANNEL) { @@ -314,7 +316,6 @@ cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset) return NULL; } else iter->devno++; - (*offset)++; return iter; } diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index cd164886132f..ee0b3c586211 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "cio.h" @@ -207,7 +208,7 @@ static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr, /* fill in sl */ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) - q->sl->element[j].sbal = (unsigned long)q->sbal[j]; + q->sl->element[j].sbal = virt_to_phys(q->sbal[j]); } static void setup_queues(struct qdio_irq *irq_ptr, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 23852888eb2c..fe70e9875bde 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1244,7 +1244,6 @@ static int qeth_osa_set_output_queues(struct qeth_card *card, bool single) if (count == 1) dev_info(&card->gdev->dev, "Priority Queueing not supported\n"); - card->qdio.default_out_queue = single ? 0 : QETH_DEFAULT_QUEUE; card->qdio.no_out_queues = count; return 0; } @@ -2634,12 +2633,12 @@ static int qeth_init_input_buffer(struct qeth_card *card, buf->rx_skb = netdev_alloc_skb(card->dev, QETH_RX_PULL_LEN + ETH_HLEN); if (!buf->rx_skb) - return 1; + return -ENOMEM; } pool_entry = qeth_find_free_buffer_pool_entry(card); if (!pool_entry) - return 1; + return -ENOBUFS; /* * since the buffer is accessed only from the input_tasklet @@ -2671,10 +2670,15 @@ int qeth_init_qdio_queues(struct qeth_card *card) /* inbound queue */ qdio_reset_buffers(card->qdio.in_q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q); memset(&card->rx, 0, sizeof(struct qeth_rx)); + qeth_initialize_working_pool_list(card); /*give only as many buffers to hardware as we have buffer pool entries*/ - for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i) - qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]); + for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; i++) { + rc = qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]); + if (rc) + return rc; + } + card->qdio.in_q->next_buf_to_init = card->qdio.in_buf_pool.buf_count - 1; rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0, @@ -4716,10 +4720,10 @@ static void qeth_qdio_establish_cq(struct qeth_card *card, if (card->options.cq == QETH_CQ_ENABLED) { int offset = QDIO_MAX_BUFFERS_PER_Q * (card->qdio.no_in_queues - 1); - for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { - in_sbal_ptrs[offset + i] = (struct qdio_buffer *) - virt_to_phys(card->qdio.c_q->bufs[i].buffer); - } + + for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) + in_sbal_ptrs[offset + i] = + card->qdio.c_q->bufs[i].buffer; queue_start_poll[card->qdio.no_in_queues - 1] = NULL; } @@ -4753,10 +4757,9 @@ static int qeth_qdio_establish(struct qeth_card *card) rc = -ENOMEM; goto out_free_qib_param; } - for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { - in_sbal_ptrs[i] = (struct qdio_buffer *) - virt_to_phys(card->qdio.in_q->bufs[i].buffer); - } + + for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) + in_sbal_ptrs[i] = card->qdio.in_q->bufs[i].buffer; queue_start_poll = kcalloc(card->qdio.no_in_queues, sizeof(void *), GFP_KERNEL); @@ -4777,11 +4780,11 @@ static int qeth_qdio_establish(struct qeth_card *card) rc = -ENOMEM; goto out_free_queue_start_poll; } + for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i) - for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) { - out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys( - card->qdio.out_qs[i]->bufs[j]->buffer); - } + for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++, k++) + out_sbal_ptrs[k] = + card->qdio.out_qs[i]->bufs[j]->buffer; memset(&init_data, 0, sizeof(struct qdio_initialize)); init_data.cdev = CARD_DDEV(card); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 079c04bc448a..7a57b61f0340 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -9947,6 +9947,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, ioa_cfg->max_devs_supported = ipr_max_devs; if (ioa_cfg->sis64) { + host->max_channel = IPR_MAX_SIS64_BUSES; host->max_id = IPR_MAX_SIS64_TARGETS_PER_BUS; host->max_lun = IPR_MAX_SIS64_LUNS_PER_TARGET; if (ipr_max_devs > IPR_MAX_SIS64_DEVS) @@ -9955,6 +9956,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, + ((sizeof(struct ipr_config_table_entry64) * ioa_cfg->max_devs_supported))); } else { + host->max_channel = IPR_VSET_BUS; host->max_id = IPR_MAX_NUM_TARGETS_PER_BUS; host->max_lun = IPR_MAX_NUM_LUNS_PER_TARGET; if (ipr_max_devs > IPR_MAX_PHYSICAL_DEVS) @@ -9964,7 +9966,6 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, * ioa_cfg->max_devs_supported))); } - host->max_channel = IPR_VSET_BUS; host->unique_id = host->host_no; host->max_cmd_len = IPR_MAX_CDB_LEN; host->can_queue = ioa_cfg->max_cmds; diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index a67baeb36d1f..b97aa9ac2ffe 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1300,6 +1300,7 @@ struct ipr_resource_entry { #define IPR_ARRAY_VIRTUAL_BUS 0x1 #define IPR_VSET_VIRTUAL_BUS 0x2 #define IPR_IOAFP_VIRTUAL_BUS 0x3 +#define IPR_MAX_SIS64_BUSES 0x4 #define IPR_GET_RES_PHYS_LOC(res) \ (((res)->bus << 24) | ((res)->target << 8) | (res)->lun) diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 9c5f7c9178c6..2b865c6423e2 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -628,6 +628,8 @@ redisc: } out: kref_put(&rdata->kref, fc_rport_destroy); + if (!IS_ERR(fp)) + fc_frame_free(fp); } /** diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 46bc062d873e..d86838801805 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -594,7 +594,8 @@ retry_alloc: fusion->io_request_frames = dma_pool_alloc(fusion->io_request_frames_pool, - GFP_KERNEL, &fusion->io_request_frames_phys); + GFP_KERNEL | __GFP_NOWARN, + &fusion->io_request_frames_phys); if (!fusion->io_request_frames) { if (instance->max_fw_cmds >= (MEGASAS_REDUCE_QD_COUNT * 2)) { instance->max_fw_cmds -= MEGASAS_REDUCE_QD_COUNT; @@ -632,7 +633,7 @@ retry_alloc: fusion->io_request_frames = dma_pool_alloc(fusion->io_request_frames_pool, - GFP_KERNEL, + GFP_KERNEL | __GFP_NOWARN, &fusion->io_request_frames_phys); if (!fusion->io_request_frames) { diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 65ce10c7989c..350dbd2bb261 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3180,9 +3180,11 @@ static int sd_revalidate_disk(struct gendisk *disk) if (sd_validate_opt_xfer_size(sdkp, dev_max)) { q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks); rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks); - } else + } else { + q->limits.io_opt = 0; rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), (sector_t)BLK_DEF_MAX_SECTORS); + } /* Do not exceed controller limit */ rw_max = min(rw_max, queue_max_hw_sectors(q)); diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c index 6feeb0faf123..7669527a70aa 100644 --- a/drivers/scsi/ufs/cdns-pltfrm.c +++ b/drivers/scsi/ufs/cdns-pltfrm.c @@ -97,7 +97,7 @@ static int cdns_ufs_link_startup_notify(struct ufs_hba *hba, * and device TX LCC are disabled once link startup is * completed. */ - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); + ufshcd_disable_host_tx_lcc(hba); /* * Disabling Autohibern8 feature in cadence UFS diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c index 63bb06acd458..e555a30f822f 100644 --- a/drivers/scsi/ufs/ufs-hisi.c +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -235,7 +235,7 @@ static int ufs_hisi_link_startup_pre_change(struct ufs_hba *hba) ufshcd_writel(hba, reg, REG_AUTO_HIBERNATE_IDLE_TIMER); /* Unipro PA_Local_TX_LCC_Enable */ - ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x155E, 0x0), 0x0); + ufshcd_disable_host_tx_lcc(hba); /* close Unipro VS_Mk2ExtnSupport */ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), 0x0); ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), &value); diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 53eae5fe2ade..de650822c9d9 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -30,6 +30,11 @@ #define ufs_mtk_device_reset_ctrl(high, res) \ ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, high, res) +#define ufs_mtk_unipro_powerdown(hba, powerdown) \ + ufshcd_dme_set(hba, \ + UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), \ + powerdown) + static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) { u32 tmp; @@ -95,6 +100,17 @@ static int ufs_mtk_bind_mphy(struct ufs_hba *hba) return err; } +static void ufs_mtk_udelay(unsigned long us) +{ + if (!us) + return; + + if (us < 10) + udelay(us); + else + usleep_range(us, us + 10); +} + static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); @@ -107,6 +123,7 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) if (on) { ufs_mtk_ref_clk_notify(on, res); + ufs_mtk_udelay(host->ref_clk_ungating_wait_us); ufshcd_writel(hba, REFCLK_REQUEST, REG_UFS_REFCLK_CTRL); } else { ufshcd_writel(hba, REFCLK_RELEASE, REG_UFS_REFCLK_CTRL); @@ -132,12 +149,40 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) out: host->ref_clk_enabled = on; - if (!on) + if (!on) { + ufs_mtk_udelay(host->ref_clk_gating_wait_us); ufs_mtk_ref_clk_notify(on, res); + } return 0; } +static void ufs_mtk_setup_ref_clk_wait_us(struct ufs_hba *hba, + u16 gating_us, u16 ungating_us) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + if (hba->dev_info.clk_gating_wait_us) { + host->ref_clk_gating_wait_us = + hba->dev_info.clk_gating_wait_us; + } else { + host->ref_clk_gating_wait_us = gating_us; + } + + host->ref_clk_ungating_wait_us = ungating_us; +} + +static u32 ufs_mtk_link_get_state(struct ufs_hba *hba) +{ + u32 val; + + ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL); + val = ufshcd_readl(hba, REG_UFS_PROBE); + val = val >> 28; + + return val; +} + /** * ufs_mtk_setup_clocks - enables/disable clocks * @hba: host controller instance @@ -150,7 +195,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); - int ret = -EINVAL; + int ret = 0; /* * In case ufs_mtk_init() is not yet done, simply ignore. @@ -160,19 +205,24 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, if (!host) return 0; - switch (status) { - case PRE_CHANGE: - if (!on) { + if (!on && status == PRE_CHANGE) { + if (!ufshcd_is_link_active(hba)) { ufs_mtk_setup_ref_clk(hba, on); ret = phy_power_off(host->mphy); + } else { + /* + * Gate ref-clk if link state is in Hibern8 + * triggered by Auto-Hibern8. + */ + if (!ufshcd_can_hibern8_during_gating(hba) && + ufshcd_is_auto_hibern8_enabled(hba) && + ufs_mtk_link_get_state(hba) == + VS_LINK_HIBERN8) + ufs_mtk_setup_ref_clk(hba, on); } - break; - case POST_CHANGE: - if (on) { - ret = phy_power_on(host->mphy); - ufs_mtk_setup_ref_clk(hba, on); - } - break; + } else if (on && status == POST_CHANGE) { + ret = phy_power_on(host->mphy); + ufs_mtk_setup_ref_clk(hba, on); } return ret; @@ -290,6 +340,17 @@ static int ufs_mtk_pre_link(struct ufs_hba *hba) int ret; u32 tmp; + ufs_mtk_unipro_powerdown(hba, 0); + + /* + * Setting PA_Local_TX_LCC_Enable to 0 before link startup + * to make sure that both host and device TX LCC are disabled + * once link startup is completed. + */ + ret = ufshcd_disable_host_tx_lcc(hba); + if (ret) + return ret; + /* disable deep stall */ ret = ufshcd_dme_get(hba, UIC_ARG_MIB(VS_SAVEPOWERCONTROL), &tmp); if (ret) @@ -321,9 +382,6 @@ static void ufs_mtk_setup_clk_gating(struct ufs_hba *hba) static int ufs_mtk_post_link(struct ufs_hba *hba) { - /* disable device LCC */ - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); - /* enable unipro clock gating feature */ ufs_mtk_cfg_unipro_cg(hba, true); @@ -390,9 +448,7 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) if (err) return err; - err = ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 0); + err = ufs_mtk_unipro_powerdown(hba, 0); if (err) return err; @@ -413,14 +469,10 @@ static int ufs_mtk_link_set_lpm(struct ufs_hba *hba) { int err; - err = ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 1); + err = ufs_mtk_unipro_powerdown(hba, 1); if (err) { /* Resume UniPro state for following error recovery */ - ufshcd_dme_set(hba, - UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - 0); + ufs_mtk_unipro_powerdown(hba, 0); return err; } @@ -436,10 +488,11 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) err = ufs_mtk_link_set_lpm(hba); if (err) return -EAGAIN; - phy_power_off(host->mphy); - ufs_mtk_setup_ref_clk(hba, false); } + if (!ufshcd_is_link_active(hba)) + phy_power_off(host->mphy); + return 0; } @@ -448,9 +501,10 @@ static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) struct ufs_mtk_host *host = ufshcd_get_variant(hba); int err; - if (ufshcd_is_link_hibern8(hba)) { - ufs_mtk_setup_ref_clk(hba, true); + if (!ufshcd_is_link_active(hba)) phy_power_on(host->mphy); + + if (ufshcd_is_link_hibern8(hba)) { err = ufs_mtk_link_set_hpm(hba); if (err) return err; @@ -477,10 +531,23 @@ static void ufs_mtk_dbg_register_dump(struct ufs_hba *hba) static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba) { struct ufs_dev_info *dev_info = &hba->dev_info; + u16 mid = dev_info->wmanufacturerid; - if (dev_info->wmanufacturerid == UFS_VENDOR_SAMSUNG) + if (mid == UFS_VENDOR_SAMSUNG) ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 6); + /* + * Decide waiting time before gating reference clock and + * after ungating reference clock according to vendors' + * requirements. + */ + if (mid == UFS_VENDOR_SAMSUNG) + ufs_mtk_setup_ref_clk_wait_us(hba, 1, 1); + else if (mid == UFS_VENDOR_SKHYNIX) + ufs_mtk_setup_ref_clk_wait_us(hba, 30, 30); + else if (mid == UFS_VENDOR_TOSHIBA) + ufs_mtk_setup_ref_clk_wait_us(hba, 100, 32); + return 0; } diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index fccdd979d6fb..4c787b99fe41 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -53,6 +53,18 @@ #define VS_SAVEPOWERCONTROL 0xD0A6 #define VS_UNIPROPOWERDOWNCONTROL 0xD0A8 +/* + * Vendor specific link state + */ +enum { + VS_LINK_DISABLED = 0, + VS_LINK_DOWN = 1, + VS_LINK_UP = 2, + VS_LINK_HIBERN8 = 3, + VS_LINK_LOST = 4, + VS_LINK_CFG = 5, +}; + /* * SiP commands */ @@ -80,6 +92,8 @@ struct ufs_mtk_host { struct ufs_hba *hba; struct phy *mphy; bool ref_clk_enabled; + u16 ref_clk_ungating_wait_us; + u16 ref_clk_gating_wait_us; }; #endif /* !_UFS_MEDIATEK_H */ diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index cac8f8b3cf89..b4217f45ac9a 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "ufshcd.h" #include "ufshcd-pltfrm.h" @@ -844,9 +845,7 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, * completed. */ if (ufshcd_get_local_unipro_ver(hba) != UFS_UNIPRO_VER_1_41) - err = ufshcd_dme_set(hba, - UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), - 0); + err = ufshcd_disable_host_tx_lcc(hba); if (err) goto out; break; @@ -1342,11 +1341,27 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable) /* * If we are here to disable this clock it might be immediately * after entering into hibern8 in which case we need to make - * sure that device ref_clk is active for a given time after + * sure that device ref_clk is active for specific time after * enter hibern8 */ - if (!enable) - udelay(50); + if (!enable) { + unsigned long gating_wait; + + gating_wait = host->hba->dev_info.clk_gating_wait_us; + if (!gating_wait) { + udelay(1); + } else { + /* + * bRefClkGatingWaitTime defines the minimum + * time for which the reference clock is + * required by device during transition from + * HS-MODE to LS-MODE or HIBERN8 state. Give it + * more delay to be on the safe side. + */ + gating_wait += 10; + usleep_range(gating_wait, gating_wait + 10); + } + } writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio); @@ -2836,6 +2851,29 @@ static void ufs_qcom_device_reset(struct ufs_hba *hba) usleep_range(10, 15); } +#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) +static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, + struct devfreq_dev_profile *p, + void *data) +{ + static struct devfreq_simple_ondemand_data *d; + + if (!data) + return; + + d = (struct devfreq_simple_ondemand_data *)data; + p->polling_ms = 60; + d->upthreshold = 70; + d->downdifferential = 5; +} +#else +static void ufs_qcom_config_scaling_param(struct ufs_hba *hba, + struct devfreq_dev_profile *p, + void *data) +{ +} +#endif + /** * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations * @@ -2857,6 +2895,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .resume = ufs_qcom_resume, .dbg_register_dump = ufs_qcom_dump_dbg_regs, .device_reset = ufs_qcom_device_reset, + .config_scaling_param = ufs_qcom_config_scaling_param, }; /** diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index cea08ad238b1..f021ce432156 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -30,8 +30,6 @@ #define UFS_HW_VER_STEP_MASK (0xFFFF << UFS_HW_VER_STEP_SHFT) /* vendor specific pre-defined parameters */ -#define UFS_HS_G4 4 /* HS Gear 4 */ - #define SLOW 1 #define FAST 2 diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 71170fda459f..a6ef96c8a1f3 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -564,7 +564,7 @@ struct ufs_dev_info { u16 wmanufacturerid; /*UFS device Product Name */ u8 *model; - u16 spec_version; + u16 wspecversion; u32 clk_gating_wait_us; }; diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c index 1075f236eb8c..4a946a5b2271 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.c +++ b/drivers/scsi/ufs/ufshcd-crypto.c @@ -456,6 +456,14 @@ int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, return ufshcd_prepare_lrbp_crypto_spec(hba, cmd, lrbp); } +int ufshcd_map_sg_crypto(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +{ + if (hba->crypto_vops && hba->crypto_vops->map_sg_crypto) + return hba->crypto_vops->map_sg_crypto(hba, lrbp); + + return 0; +} + int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp) diff --git a/drivers/scsi/ufs/ufshcd-crypto.h b/drivers/scsi/ufs/ufshcd-crypto.h index 95f37c9f7672..f223a06fbf93 100644 --- a/drivers/scsi/ufs/ufshcd-crypto.h +++ b/drivers/scsi/ufs/ufshcd-crypto.h @@ -80,6 +80,8 @@ int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp); +int ufshcd_map_sg_crypto(struct ufs_hba *hba, struct ufshcd_lrb *lrbp); + int ufshcd_complete_lrbp_crypto(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp); @@ -133,6 +135,12 @@ static inline int ufshcd_prepare_lrbp_crypto(struct ufs_hba *hba, return 0; } +static inline int ufshcd_map_sg_crypto(struct ufs_hba *hba, + struct ufshcd_lrb *lrbp) +{ + return 0; +} + static inline bool ufshcd_lrbp_crypto_enabled(struct ufshcd_lrb *lrbp) { return false; diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 3b19de3ae9a3..8f78a8151499 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -44,7 +44,7 @@ static int ufs_intel_disable_lcc(struct ufs_hba *hba) ufshcd_dme_get(hba, attr, &lcc_enable); if (lcc_enable) - ufshcd_dme_set(hba, attr, 0); + ufshcd_disable_host_tx_lcc(hba); return 0; } diff --git a/drivers/scsi/ufs/ufshcd-qti.c b/drivers/scsi/ufs/ufshcd-qti.c index 4cb71940b793..1bcd6992f890 100644 --- a/drivers/scsi/ufs/ufshcd-qti.c +++ b/drivers/scsi/ufs/ufshcd-qti.c @@ -5332,7 +5332,7 @@ static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer) return err; } -static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba) +static inline int ufshcd_qti_disable_host_tx_lcc(struct ufs_hba *hba) { return ufshcd_disable_tx_lcc(hba, false); } @@ -5398,7 +5398,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba) } if (hba->dev_quirks & UFS_DEVICE_QUIRK_BROKEN_LCC) { - ret = ufshcd_disable_host_tx_lcc(hba); + ret = ufshcd_qti_disable_host_tx_lcc(hba); if (ret) goto out; } @@ -7683,7 +7683,7 @@ static int ufshcd_set_low_vcc_level(struct ufs_hba *hba) struct ufs_vreg *vreg = hba->vreg_info.vcc; /* Check if device supports the low voltage VCC feature */ - if (hba->dev_info.spec_version < 0x300) + if (hba->dev_info.wspecversion < 0x300) return 0; /* @@ -7816,7 +7816,7 @@ static int ufs_get_device_desc(struct ufs_hba *hba) dev_info->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 | desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]; - dev_info->spec_version = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 | + dev_info->wspecversion = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 | desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1]; dev_info->b_device_sub_class = desc_buf[DEVICE_DESC_PARAM_DEVICE_SUB_CLASS]; @@ -8182,7 +8182,7 @@ static int ufshcd_get_dev_ref_clk_gating_wait(struct ufs_hba *hba) int err = 0; u32 gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US; - if (hba->dev_info.spec_version >= 0x300) { + if (hba->dev_info.wspecversion >= 0x300) { err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME, 0, 0, &gating_wait); @@ -8254,7 +8254,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) ufshcd_tune_unipro_params(hba); ufshcd_apply_pm_quirks(hba); - if (hba->dev_info.spec_version < 0x300) { + if (hba->dev_info.wspecversion < 0x300) { ret = ufshcd_set_vccq_rail_unused(hba, (hba->dev_quirks & UFS_DEVICE_NO_VCCQ) ? true : false); @@ -8270,9 +8270,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) * during system suspend events. This will cause the UFS * device to re-initialize upon system resume events. */ - if ((hba->dev_info.spec_version >= 0x300 && hba->vreg_info.vccq && + if ((hba->dev_info.wspecversion >= 0x300 && hba->vreg_info.vccq && hba->vreg_info.vccq->sys_suspend_pwr_off) || - (hba->dev_info.spec_version < 0x300 && hba->vreg_info.vccq2 && + (hba->dev_info.wspecversion < 0x300 && hba->vreg_info.vccq2 && hba->vreg_info.vccq2->sys_suspend_pwr_off)) hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_POWERDOWN_PWR_MODE, @@ -9104,14 +9104,14 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) && !hba->dev_info.is_lu_power_on_wp) { ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); - if (hba->dev_info.spec_version >= 0x300 && + if (hba->dev_info.wspecversion >= 0x300 && hba->vreg_info.vccq->sys_suspend_pwr_off) ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq, false); else ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); - if (hba->dev_info.spec_version < 0x300 && + if (hba->dev_info.wspecversion < 0x300 && hba->vreg_info.vccq2->sys_suspend_pwr_off) ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq2, false); @@ -9132,7 +9132,7 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) && !hba->dev_info.is_lu_power_on_wp) { - if (hba->dev_info.spec_version < 0x300 && + if (hba->dev_info.wspecversion < 0x300 && hba->vreg_info.vccq2->sys_suspend_pwr_off) ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq2, true); @@ -9141,7 +9141,7 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) if (ret) goto vcc_disable; - if (hba->dev_info.spec_version >= 0x300 && + if (hba->dev_info.wspecversion >= 0x300 && hba->vreg_info.vccq->sys_suspend_pwr_off) ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq, true); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d62d0cbbea48..77aa0e1900ee 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "ufshcd.h" #include "ufs_quirks.h" #include "unipro.h" @@ -172,19 +173,6 @@ enum { #define ufshcd_clear_eh_in_progress(h) \ ((h)->eh_flags &= ~UFSHCD_EH_IN_PROGRESS) -#define ufshcd_set_ufs_dev_active(h) \ - ((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE) -#define ufshcd_set_ufs_dev_sleep(h) \ - ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE) -#define ufshcd_set_ufs_dev_poweroff(h) \ - ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE) -#define ufshcd_is_ufs_dev_active(h) \ - ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE) -#define ufshcd_is_ufs_dev_sleep(h) \ - ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE) -#define ufshcd_is_ufs_dev_poweroff(h) \ - ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE) - struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { {UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE}, {UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE}, @@ -244,13 +232,13 @@ static struct ufs_dev_fix ufs_fixups[] = { END_FIX }; -static void ufshcd_tmc_handler(struct ufs_hba *hba); +static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd); static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); static void ufshcd_hba_exit(struct ufs_hba *hba); -static int ufshcd_probe_hba(struct ufs_hba *hba); +static int ufshcd_probe_hba(struct ufs_hba *hba, bool async); static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, bool skip_ref_clk); static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); @@ -1263,6 +1251,9 @@ static int ufshcd_devfreq_target(struct device *dev, if (!ufshcd_is_clkscaling_supported(hba)) return -EINVAL; + clki = list_first_entry(&hba->clk_list_head, struct ufs_clk_info, list); + /* Override with the closest supported frequency */ + *freq = (unsigned long) clk_round_rate(clki->clk, *freq); spin_lock_irqsave(hba->host->host_lock, irq_flags); if (ufshcd_eh_in_progress(hba)) { spin_unlock_irqrestore(hba->host->host_lock, irq_flags); @@ -1277,8 +1268,11 @@ static int ufshcd_devfreq_target(struct device *dev, goto out; } - clki = list_first_entry(&hba->clk_list_head, struct ufs_clk_info, list); + /* Decide based on the rounded-off frequency and update */ scale_up = (*freq == clki->max_freq) ? true : false; + if (!scale_up) + *freq = clki->min_freq; + /* Update the frequency */ if (!ufshcd_is_devfreq_scaling_required(hba, scale_up)) { spin_unlock_irqrestore(hba->host->host_lock, irq_flags); ret = 0; @@ -1308,6 +1302,8 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, struct ufs_hba *hba = dev_get_drvdata(dev); struct ufs_clk_scaling *scaling = &hba->clk_scaling; unsigned long flags; + struct list_head *clk_list = &hba->clk_list_head; + struct ufs_clk_info *clki; if (!ufshcd_is_clkscaling_supported(hba)) return -EINVAL; @@ -1318,6 +1314,13 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, if (!scaling->window_start_t) goto start_window; + clki = list_first_entry(clk_list, struct ufs_clk_info, list); + /* + * If current frequency is 0, then the ondemand governor considers + * there's no initial frequency set. And it always requests to set + * to max. frequency. + */ + stat->current_frequency = clki->curr_freq; if (scaling->is_busy_started) scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(), scaling->busy_start_t)); @@ -1346,6 +1349,17 @@ static struct devfreq_dev_profile ufs_devfreq_profile = { .get_dev_status = ufshcd_devfreq_get_dev_status, }; +#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) +static struct devfreq_simple_ondemand_data ufs_ondemand_data = { + .upthreshold = 70, + .downdifferential = 5, +}; + +static void *gov_data = &ufs_ondemand_data; +#else +static void *gov_data; /* NULL */ +#endif + static int ufshcd_devfreq_init(struct ufs_hba *hba) { struct list_head *clk_list = &hba->clk_list_head; @@ -1361,10 +1375,12 @@ static int ufshcd_devfreq_init(struct ufs_hba *hba) dev_pm_opp_add(hba->dev, clki->min_freq, 0); dev_pm_opp_add(hba->dev, clki->max_freq, 0); + ufshcd_vops_config_scaling_param(hba, &ufs_devfreq_profile, + gov_data); devfreq = devfreq_add_device(hba->dev, &ufs_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND, - NULL); + gov_data); if (IS_ERR(devfreq)) { ret = PTR_ERR(devfreq); dev_err(hba->dev, "Unable to register with devfreq %d\n", ret); @@ -1645,7 +1661,7 @@ static void ufshcd_gate_work(struct work_struct *work) * state to CLKS_ON. */ if (hba->clk_gating.is_suspended || - (hba->clk_gating.state == REQ_CLKS_ON)) { + (hba->clk_gating.state != REQ_CLKS_OFF)) { hba->clk_gating.state = CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); @@ -2176,7 +2192,7 @@ static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) lrbp->utr_descriptor_ptr->prd_table_length = 0; } - return 0; + return ufshcd_map_sg_crypto(hba, lrbp); } /** @@ -3421,7 +3437,7 @@ static int ufshcd_get_ref_clk_gating_wait(struct ufs_hba *hba) int err = 0; u32 gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US; - if (hba->dev_info.spec_version >= 0x300) { + if (hba->dev_info.wspecversion >= 0x300) { err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME, 0, 0, &gating_wait); @@ -3435,13 +3451,7 @@ static int ufshcd_get_ref_clk_gating_wait(struct ufs_hba *hba) gating_wait); } - /* - * bRefClkGatingWaitTime defines the minimum time for which the - * reference clock is required by device during transition from - * HS-MODE to LS-MODE or HIBERN8 state. Give it more time to be - * on the safe side. - */ - hba->dev_info.clk_gating_wait_us = gating_wait + 50; + hba->dev_info.clk_gating_wait_us = gating_wait; } return err; @@ -3954,6 +3964,9 @@ static int ufshcd_link_recovery(struct ufs_hba *hba) ufshcd_set_eh_in_progress(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); + /* Reset the attached device */ + ufshcd_vops_device_reset(hba); + ret = ufshcd_host_reset_and_restore(hba); spin_lock_irqsave(hba->host->host_lock, flags); @@ -4053,18 +4066,25 @@ EXPORT_SYMBOL_GPL(ufshcd_uic_hibern8_exit); void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit) { unsigned long flags; + bool update = false; - if (!(hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT)) + if (!ufshcd_is_auto_hibern8_supported(hba)) return; spin_lock_irqsave(hba->host->host_lock, flags); - if (hba->ahit == ahit) - goto out_unlock; - hba->ahit = ahit; - if (!pm_runtime_suspended(hba->dev)) - ufshcd_writel(hba, hba->ahit, REG_AUTO_HIBERNATE_IDLE_TIMER); -out_unlock: + if (hba->ahit != ahit) { + hba->ahit = ahit; + update = true; + } spin_unlock_irqrestore(hba->host->host_lock, flags); + + if (update && !pm_runtime_suspended(hba->dev)) { + pm_runtime_get_sync(hba->dev); + ufshcd_hold(hba, false); + ufshcd_auto_hibern8_enable(hba); + ufshcd_release(hba); + pm_runtime_put(hba->dev); + } } EXPORT_SYMBOL_GPL(ufshcd_auto_hibern8_update); @@ -4968,19 +4988,29 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) * ufshcd_uic_cmd_compl - handle completion of uic command * @hba: per adapter instance * @intr_status: interrupt status generated by the controller + * + * Returns + * IRQ_HANDLED - If interrupt is valid + * IRQ_NONE - If invalid interrupt */ -static void ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) +static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status) { + irqreturn_t retval = IRQ_NONE; + if ((intr_status & UIC_COMMAND_COMPL) && hba->active_uic_cmd) { hba->active_uic_cmd->argument2 |= ufshcd_get_uic_cmd_result(hba); hba->active_uic_cmd->argument3 = ufshcd_get_dme_attr_val(hba); complete(&hba->active_uic_cmd->done); + retval = IRQ_HANDLED; } - if ((intr_status & UFSHCD_UIC_PWR_MASK) && hba->uic_async_done) + if ((intr_status & UFSHCD_UIC_PWR_MASK) && hba->uic_async_done) { complete(hba->uic_async_done); + retval = IRQ_HANDLED; + } + return retval; } /** @@ -5037,8 +5067,12 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, /** * ufshcd_transfer_req_compl - handle SCSI and query command completion * @hba: per adapter instance + * + * Returns + * IRQ_HANDLED - If interrupt is valid + * IRQ_NONE - If invalid interrupt */ -static void ufshcd_transfer_req_compl(struct ufs_hba *hba) +static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba) { unsigned long completed_reqs; u32 tr_doorbell; @@ -5057,7 +5091,12 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); completed_reqs = tr_doorbell ^ hba->outstanding_reqs; - __ufshcd_transfer_req_compl(hba, completed_reqs); + if (completed_reqs) { + __ufshcd_transfer_req_compl(hba, completed_reqs); + return IRQ_HANDLED; + } else { + return IRQ_NONE; + } } /** @@ -5586,67 +5625,84 @@ out: /** * ufshcd_update_uic_error - check and set fatal UIC error flags. * @hba: per-adapter instance + * + * Returns + * IRQ_HANDLED - If interrupt is valid + * IRQ_NONE - If invalid interrupt */ -static void ufshcd_update_uic_error(struct ufs_hba *hba) +static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba) { u32 reg; + irqreturn_t retval = IRQ_NONE; /* PHY layer lane error */ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER); /* Ignore LINERESET indication, as this is not an error */ if ((reg & UIC_PHY_ADAPTER_LAYER_ERROR) && - (reg & UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK)) { + (reg & UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK)) { /* * To know whether this error is fatal or not, DB timeout * must be checked but this error is handled separately. */ dev_dbg(hba->dev, "%s: UIC Lane error reported\n", __func__); ufshcd_update_reg_hist(&hba->ufs_stats.pa_err, reg); + retval |= IRQ_HANDLED; } /* PA_INIT_ERROR is fatal and needs UIC reset */ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER); - if (reg) + if ((reg & UIC_DATA_LINK_LAYER_ERROR) && + (reg & UIC_DATA_LINK_LAYER_ERROR_CODE_MASK)) { ufshcd_update_reg_hist(&hba->ufs_stats.dl_err, reg); - if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT) - hba->uic_error |= UFSHCD_UIC_DL_PA_INIT_ERROR; - else if (hba->dev_quirks & - UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) { - if (reg & UIC_DATA_LINK_LAYER_ERROR_NAC_RECEIVED) - hba->uic_error |= - UFSHCD_UIC_DL_NAC_RECEIVED_ERROR; - else if (reg & UIC_DATA_LINK_LAYER_ERROR_TCx_REPLAY_TIMEOUT) - hba->uic_error |= UFSHCD_UIC_DL_TCx_REPLAY_ERROR; + if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT) + hba->uic_error |= UFSHCD_UIC_DL_PA_INIT_ERROR; + else if (hba->dev_quirks & + UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) { + if (reg & UIC_DATA_LINK_LAYER_ERROR_NAC_RECEIVED) + hba->uic_error |= + UFSHCD_UIC_DL_NAC_RECEIVED_ERROR; + else if (reg & UIC_DATA_LINK_LAYER_ERROR_TCx_REPLAY_TIMEOUT) + hba->uic_error |= UFSHCD_UIC_DL_TCx_REPLAY_ERROR; + } + retval |= IRQ_HANDLED; } /* UIC NL/TL/DME errors needs software retry */ reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_NETWORK_LAYER); - if (reg) { + if ((reg & UIC_NETWORK_LAYER_ERROR) && + (reg & UIC_NETWORK_LAYER_ERROR_CODE_MASK)) { ufshcd_update_reg_hist(&hba->ufs_stats.nl_err, reg); hba->uic_error |= UFSHCD_UIC_NL_ERROR; + retval |= IRQ_HANDLED; } reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_TRANSPORT_LAYER); - if (reg) { + if ((reg & UIC_TRANSPORT_LAYER_ERROR) && + (reg & UIC_TRANSPORT_LAYER_ERROR_CODE_MASK)) { ufshcd_update_reg_hist(&hba->ufs_stats.tl_err, reg); hba->uic_error |= UFSHCD_UIC_TL_ERROR; + retval |= IRQ_HANDLED; } reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DME); - if (reg) { + if ((reg & UIC_DME_ERROR) && + (reg & UIC_DME_ERROR_CODE_MASK)) { ufshcd_update_reg_hist(&hba->ufs_stats.dme_err, reg); hba->uic_error |= UFSHCD_UIC_DME_ERROR; + retval |= IRQ_HANDLED; } dev_dbg(hba->dev, "%s: UIC error flags = 0x%08x\n", __func__, hba->uic_error); + return retval; } static bool ufshcd_is_auto_hibern8_error(struct ufs_hba *hba, u32 intr_mask) { - if (!ufshcd_is_auto_hibern8_supported(hba)) + if (!ufshcd_is_auto_hibern8_supported(hba) || + !ufshcd_is_auto_hibern8_enabled(hba)) return false; if (!(intr_mask & UFSHCD_UIC_HIBERN8_MASK)) @@ -5663,10 +5719,15 @@ static bool ufshcd_is_auto_hibern8_error(struct ufs_hba *hba, /** * ufshcd_check_errors - Check for errors that need s/w attention * @hba: per-adapter instance + * + * Returns + * IRQ_HANDLED - If interrupt is valid + * IRQ_NONE - If invalid interrupt */ -static void ufshcd_check_errors(struct ufs_hba *hba) +static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba) { bool queue_eh_work = false; + irqreturn_t retval = IRQ_NONE; if (hba->errors & INT_FATAL_ERRORS) { ufshcd_update_reg_hist(&hba->ufs_stats.fatal_err, hba->errors); @@ -5675,7 +5736,7 @@ static void ufshcd_check_errors(struct ufs_hba *hba) if (hba->errors & UIC_ERROR) { hba->uic_error = 0; - ufshcd_update_uic_error(hba); + retval = ufshcd_update_uic_error(hba); if (hba->uic_error) queue_eh_work = true; } @@ -5723,6 +5784,7 @@ static void ufshcd_check_errors(struct ufs_hba *hba) } schedule_work(&hba->eh_work); } + retval |= IRQ_HANDLED; } /* * if (!queue_eh_work) - @@ -5730,44 +5792,62 @@ static void ufshcd_check_errors(struct ufs_hba *hba) * itself without s/w intervention or errors that will be * handled by the SCSI core layer. */ + return retval; } /** * ufshcd_tmc_handler - handle task management function completion * @hba: per adapter instance + * + * Returns + * IRQ_HANDLED - If interrupt is valid + * IRQ_NONE - If invalid interrupt */ -static void ufshcd_tmc_handler(struct ufs_hba *hba) +static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba) { u32 tm_doorbell; tm_doorbell = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL); hba->tm_condition = tm_doorbell ^ hba->outstanding_tasks; - wake_up(&hba->tm_wq); + if (hba->tm_condition) { + wake_up(&hba->tm_wq); + return IRQ_HANDLED; + } else { + return IRQ_NONE; + } } /** * ufshcd_sl_intr - Interrupt service routine * @hba: per adapter instance * @intr_status: contains interrupts generated by the controller + * + * Returns + * IRQ_HANDLED - If interrupt is valid + * IRQ_NONE - If invalid interrupt */ -static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status) +static irqreturn_t ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status) { + irqreturn_t retval = IRQ_NONE; + hba->errors = UFSHCD_ERROR_MASK & intr_status; if (ufshcd_is_auto_hibern8_error(hba, intr_status)) hba->errors |= (UFSHCD_UIC_HIBERN8_MASK & intr_status); if (hba->errors) - ufshcd_check_errors(hba); + retval |= ufshcd_check_errors(hba); if (intr_status & UFSHCD_UIC_MASK) - ufshcd_uic_cmd_compl(hba, intr_status); + retval |= ufshcd_uic_cmd_compl(hba, intr_status); if (intr_status & UTP_TASK_REQ_COMPL) - ufshcd_tmc_handler(hba); + retval |= ufshcd_tmc_handler(hba); if (intr_status & UTP_TRANSFER_REQ_COMPL) - ufshcd_transfer_req_compl(hba); + retval |= ufshcd_transfer_req_compl(hba); + + return retval; } /** @@ -5775,8 +5855,9 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status) * @irq: irq number * @__hba: pointer to adapter instance * - * Returns IRQ_HANDLED - If interrupt is valid - * IRQ_NONE - If invalid interrupt + * Returns + * IRQ_HANDLED - If interrupt is valid + * IRQ_NONE - If invalid interrupt */ static irqreturn_t ufshcd_intr(int irq, void *__hba) { @@ -5799,14 +5880,18 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba) intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE); if (intr_status) ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS); - if (enabled_intr_status) { - ufshcd_sl_intr(hba, enabled_intr_status); - retval = IRQ_HANDLED; - } + if (enabled_intr_status) + retval |= ufshcd_sl_intr(hba, enabled_intr_status); intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS); } while (intr_status && --retries); + if (retval == IRQ_NONE) { + dev_err(hba->dev, "%s: Unhandled interrupt 0x%08x\n", + __func__, intr_status); + ufshcd_dump_regs(hba, 0, UFSHCI_REG_SPACE_SIZE, "host_regs: "); + } + spin_unlock(hba->host->host_lock); return retval; } @@ -6403,7 +6488,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) goto out; /* Establish the link again and restore the device */ - err = ufshcd_probe_hba(hba); + err = ufshcd_probe_hba(hba, false); if (!err && (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL)) err = -EIO; @@ -6614,6 +6699,16 @@ out: kfree(desc_buf); } +static inline void ufshcd_blk_pm_runtime_init(struct scsi_device *sdev) +{ + scsi_autopm_get_device(sdev); + blk_pm_runtime_init(sdev->request_queue, &sdev->sdev_gendev); + if (sdev->rpm_autosuspend) + pm_runtime_set_autosuspend_delay(&sdev->sdev_gendev, + RPM_AUTOSUSPEND_DELAY_MS); + scsi_autopm_put_device(sdev); +} + /** * ufshcd_scsi_add_wlus - Adds required W-LUs * @hba: per-adapter instance @@ -6653,6 +6748,7 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) hba->sdev_ufs_device = NULL; goto out; } + ufshcd_blk_pm_runtime_init(hba->sdev_ufs_device); scsi_device_put(hba->sdev_ufs_device); sdev_rpmb = __scsi_add_device(hba->host, 0, 0, @@ -6661,14 +6757,17 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) ret = PTR_ERR(sdev_rpmb); goto remove_sdev_ufs_device; } + ufshcd_blk_pm_runtime_init(sdev_rpmb); scsi_device_put(sdev_rpmb); sdev_boot = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); - if (IS_ERR(sdev_boot)) + if (IS_ERR(sdev_boot)) { dev_err(hba->dev, "%s: BOOT WLUN not found\n", __func__); - else + } else { + ufshcd_blk_pm_runtime_init(sdev_boot); scsi_device_put(sdev_boot); + } goto out; remove_sdev_ufs_device: @@ -6708,7 +6807,7 @@ static int ufs_get_device_desc(struct ufs_hba *hba) desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]; /* getting Specification Version in big endian format */ - hba->dev_info.spec_version = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 | + dev_info->wspecversion = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 | desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1]; model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME]; @@ -6720,6 +6819,8 @@ static int ufs_get_device_desc(struct ufs_hba *hba) goto out; } + ufshcd_get_ref_clk_gating_wait(hba); + /* * ufshcd_read_string_desc returns size of the string * reset the error value @@ -7038,13 +7139,83 @@ out: return err; } +static int ufshcd_device_params_init(struct ufs_hba *hba) +{ + bool flag; + int ret; + + /* Init check for device descriptor sizes */ + ufshcd_init_desc_sizes(hba); + + /* Check and apply UFS device quirks */ + ret = ufs_get_device_desc(hba); + if (ret) { + dev_err(hba->dev, "%s: Failed getting device info. err = %d\n", + __func__, ret); + goto out; + } + + ufs_fixup_device_setup(hba); + + /* Clear any previous UFS device information */ + memset(&hba->dev_info, 0, sizeof(hba->dev_info)); + if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG, + QUERY_FLAG_IDN_PWR_ON_WPE, &flag)) + hba->dev_info.f_power_on_wp_en = flag; + + /* Probe maximum power mode co-supported by both UFS host and device */ + if (ufshcd_get_max_pwr_mode(hba)) + dev_err(hba->dev, + "%s: Failed getting max supported power mode\n", + __func__); +out: + return ret; +} + +/** + * ufshcd_add_lus - probe and add UFS logical units + * @hba: per-adapter instance + */ +static int ufshcd_add_lus(struct ufs_hba *hba) +{ + int ret; + + /* Add required well known logical units to scsi mid layer */ + ret = ufshcd_scsi_add_wlus(hba); + if (ret) + goto out; + + /* Initialize devfreq after UFS device is detected */ + if (ufshcd_is_clkscaling_supported(hba)) { + memcpy(&hba->clk_scaling.saved_pwr_info.info, + &hba->pwr_info, + sizeof(struct ufs_pa_layer_attr)); + hba->clk_scaling.saved_pwr_info.is_valid = true; + if (!hba->devfreq) { + ret = ufshcd_devfreq_init(hba); + if (ret) + goto out; + } + + hba->clk_scaling.is_allowed = true; + } + + ufs_bsg_probe(hba); + scsi_scan_host(hba->host); + pm_runtime_put_sync(hba->dev); + +out: + return ret; +} + /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance + * @async: asynchronous execution or not * * Execute link-startup and verify device initialization */ -static int ufshcd_probe_hba(struct ufs_hba *hba) +static int ufshcd_probe_hba(struct ufs_hba *hba, bool async) { int ret; ktime_t start = ktime_get(); @@ -7063,25 +7234,26 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) /* UniPro link is active now */ ufshcd_set_link_active(hba); + /* Verify device initialization by sending NOP OUT UPIU */ ret = ufshcd_verify_dev_init(hba); if (ret) goto out; + /* Initiate UFS initialization, and waiting until completion */ ret = ufshcd_complete_dev_init(hba); if (ret) goto out; - /* Init check for device descriptor sizes */ - ufshcd_init_desc_sizes(hba); - - ret = ufs_get_device_desc(hba); - if (ret) { - dev_err(hba->dev, "%s: Failed getting device info. err = %d\n", - __func__, ret); - goto out; + /* + * Initialize UFS device parameters used by driver, these + * parameters are associated with UFS descriptors. + */ + if (async) { + ret = ufshcd_device_params_init(hba); + if (ret) + goto out; } - ufs_fixup_device_setup(hba); ufshcd_tune_unipro_params(hba); /* UFS device is also active now */ @@ -7089,11 +7261,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) ufshcd_force_reset_auto_bkops(hba); hba->wlun_dev_clr_ua = true; - if (ufshcd_get_max_pwr_mode(hba)) { - dev_err(hba->dev, - "%s: Failed getting max supported power mode\n", - __func__); - } else { + /* Gear up to HS gear if supported */ + if (hba->max_pwr_info.is_valid) { /* * Set the right value to bRefClkFreq before attempting to * switch to HS gears. @@ -7123,57 +7292,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) /* Enable Auto-Hibernate if configured */ ufshcd_auto_hibern8_enable(hba); - /* - * If we are in error handling context or in power management callbacks - * context, no need to scan the host - */ - if (!ufshcd_eh_in_progress(hba) && !hba->pm_op_in_progress) { - bool flag; - - /* clear any previous UFS device information */ - memset(&hba->dev_info, 0, sizeof(hba->dev_info)); - - ufshcd_get_ref_clk_gating_wait(hba); - - if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG, - QUERY_FLAG_IDN_PWR_ON_WPE, &flag)) - hba->dev_info.f_power_on_wp_en = flag; - - /* Add required well known logical units to scsi mid layer */ - ret = ufshcd_scsi_add_wlus(hba); - if (ret) - goto out; - - /* Initialize devfreq after UFS device is detected */ - if (ufshcd_is_clkscaling_supported(hba)) { - memcpy(&hba->clk_scaling.saved_pwr_info.info, - &hba->pwr_info, - sizeof(struct ufs_pa_layer_attr)); - hba->clk_scaling.saved_pwr_info.is_valid = true; - if (!hba->devfreq) { - ret = ufshcd_devfreq_init(hba); - if (ret) - goto out; - } - hba->clk_scaling.is_allowed = true; - } - - ufs_bsg_probe(hba); - - scsi_scan_host(hba->host); - pm_runtime_put_sync(hba->dev); - } - out: - /* - * If we failed to initialize the device or the device is not - * present, turn off the power/clocks etc. - */ - if (ret && !ufshcd_eh_in_progress(hba) && !hba->pm_op_in_progress) { - pm_runtime_put_sync(hba->dev); - ufshcd_exit_clk_scaling(hba); - ufshcd_hba_exit(hba); - } trace_ufshcd_init(dev_name(hba->dev), ret, ktime_to_us(ktime_sub(ktime_get(), start)), @@ -7189,8 +7308,25 @@ out: static void ufshcd_async_scan(void *data, async_cookie_t cookie) { struct ufs_hba *hba = (struct ufs_hba *)data; + int ret; - ufshcd_probe_hba(hba); + /* Initialize hba, detect and initialize UFS device */ + ret = ufshcd_probe_hba(hba, true); + if (ret) + goto out; + + /* Probe and add UFS logical units */ + ret = ufshcd_add_lus(hba); +out: + /* + * If we failed to initialize the device or the device is not + * present, turn off the power/clocks etc. + */ + if (ret) { + pm_runtime_put_sync(hba->dev); + ufshcd_exit_clk_scaling(hba); + ufshcd_hba_exit(hba); + } } static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd) @@ -7462,17 +7598,12 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, struct ufs_clk_info *clki; struct list_head *head = &hba->clk_list_head; unsigned long flags; - unsigned long gating_wait; ktime_t start = ktime_get(); bool clk_state_changed = false; if (list_empty(head)) goto out; - gating_wait = (unsigned long)hba->dev_info.clk_gating_wait_us; - if (!on && !skip_ref_clk && !!gating_wait) - usleep_range(gating_wait, gating_wait + 10); - ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE); if (ret) return ret; @@ -8108,9 +8239,13 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) else goto vendor_suspend; } else if (ufshcd_is_link_off(hba)) { - ret = ufshcd_host_reset_and_restore(hba); /* - * ufshcd_host_reset_and_restore() should have already + * A full initialization of the host and the device is required + * since the link was put to off during suspend. + */ + ret = ufshcd_reset_and_restore(hba); + /* + * ufshcd_reset_and_restore() should have already * set the link state as active */ if (ret || !ufshcd_is_link_active(hba)) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 8c4f33828f09..35d27896d028 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -55,6 +55,8 @@ #include #include #include +#include +#include #include "unipro.h" #include @@ -129,6 +131,20 @@ enum uic_link_state { UIC_LINK_ACTIVE_STATE) #define ufshcd_set_link_hibern8(hba) ((hba)->uic_link_state = \ UIC_LINK_HIBERN8_STATE) + +#define ufshcd_set_ufs_dev_active(h) \ + ((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE) +#define ufshcd_set_ufs_dev_sleep(h) \ + ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE) +#define ufshcd_set_ufs_dev_poweroff(h) \ + ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE) +#define ufshcd_is_ufs_dev_active(h) \ + ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE) +#define ufshcd_is_ufs_dev_sleep(h) \ + ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE) +#define ufshcd_is_ufs_dev_poweroff(h) \ + ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE) + enum { /* errors which require the host controller reset for recovery */ UFS_ERR_HIBERN8_EXIT, @@ -361,6 +377,9 @@ struct ufs_hba_variant_ops { void (*device_reset)(struct ufs_hba *hba); int (*program_key)(struct ufs_hba *hba, const union ufs_crypto_cfg_entry *cfg, int slot); + void (*config_scaling_param)(struct ufs_hba *hba, + struct devfreq_dev_profile *profile, + void *data); }; struct keyslot_mgmt_ll_ops; @@ -379,6 +398,7 @@ struct ufs_hba_crypto_variant_ops { int (*prepare_lrbp_crypto)(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp); + int (*map_sg_crypto)(struct ufs_hba *hba, struct ufshcd_lrb *lrbp); int (*complete_lrbp_crypto)(struct ufs_hba *hba, struct scsi_cmnd *cmd, struct ufshcd_lrb *lrbp); @@ -1054,6 +1074,11 @@ static inline bool ufshcd_is_embedded_dev(struct ufs_hba *hba) return true; return false; } +#else +static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba) +{ + return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit) ? true : false; +} #endif #define ufshcd_writel(hba, val, reg) \ @@ -1190,6 +1215,11 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info) pwr_info->pwr_tx == FASTAUTO_MODE); } +static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba) +{ + return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); +} + /* Expose Query-Request API */ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, enum query_opcode opcode, @@ -1380,10 +1410,19 @@ static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) { if (hba->vops && hba->vops->device_reset) { hba->vops->device_reset(hba); + ufshcd_set_ufs_dev_active(hba); ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0); } } +static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba, + struct devfreq_dev_profile + *profile, void *data) +{ + if (hba->vops && hba->vops->config_scaling_param) + hba->vops->config_scaling_param(hba, profile, data); +} + extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; /* diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index 932a7e2864ee..18a0a2b18107 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -240,7 +240,7 @@ enum ufshcd_ec_dl { #endif /* UECDL - Host UIC Error Code Data Link Layer 3Ch */ #define UIC_DATA_LINK_LAYER_ERROR 0x80000000 -#define UIC_DATA_LINK_LAYER_ERROR_CODE_MASK 0x7FFF +#define UIC_DATA_LINK_LAYER_ERROR_CODE_MASK 0xFFFF #define UIC_DATA_LINK_LAYER_ERROR_TCX_REP_TIMER_EXP 0x2 #define UIC_DATA_LINK_LAYER_ERROR_AFCX_REQ_TIMER_EXP 0x4 #define UIC_DATA_LINK_LAYER_ERROR_FCX_PRO_TIMER_EXP 0x8 diff --git a/drivers/soc/imx/soc-imx-scu.c b/drivers/soc/imx/soc-imx-scu.c index c68882eb80f7..f638e7790470 100644 --- a/drivers/soc/imx/soc-imx-scu.c +++ b/drivers/soc/imx/soc-imx-scu.c @@ -25,7 +25,7 @@ struct imx_sc_msg_misc_get_soc_id { u32 id; } resp; } data; -} __packed; +} __packed __aligned(4); struct imx_sc_msg_misc_get_soc_uid { struct imx_sc_rpc_msg hdr; diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c index fd8007ebb145..13def7f78b9e 100644 --- a/drivers/spi/atmel-quadspi.c +++ b/drivers/spi/atmel-quadspi.c @@ -149,6 +149,7 @@ struct atmel_qspi { struct clk *qspick; struct platform_device *pdev; const struct atmel_qspi_caps *caps; + resource_size_t mmap_size; u32 pending; u32 mr; u32 scr; @@ -329,6 +330,14 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) u32 sr, offset; int err; + /* + * Check if the address exceeds the MMIO window size. An improvement + * would be to add support for regular SPI mode and fall back to it + * when the flash memories overrun the controller's memory space. + */ + if (op->addr.val + op->data.nbytes > aq->mmap_size) + return -ENOTSUPP; + err = atmel_qspi_set_cfg(aq, op, &offset); if (err) return err; @@ -480,6 +489,8 @@ static int atmel_qspi_probe(struct platform_device *pdev) goto exit; } + aq->mmap_size = resource_size(res); + /* Get the peripheral clock */ aq->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(aq->pclk)) diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index c6836a931dbf..36f7eb8ab2df 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -367,7 +367,6 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) goto out_disable_clk; rate = clk_get_rate(pll_clk); - clk_disable_unprepare(pll_clk); if (!rate) { ret = -EINVAL; goto out_disable_pll_clk; diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 848e03e5f42d..4433cb4de564 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -985,20 +985,12 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, * Note that we currently allow DMA only if we get a channel * for both rx and tx. Otherwise we'll do PIO for both rx and tx. */ -static int omap2_mcspi_request_dma(struct spi_device *spi) +static int omap2_mcspi_request_dma(struct omap2_mcspi *mcspi, + struct omap2_mcspi_dma *mcspi_dma) { - struct spi_master *master = spi->master; - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; int ret = 0; - mcspi = spi_master_get_devdata(master); - mcspi_dma = mcspi->dma_channels + spi->chip_select; - - init_completion(&mcspi_dma->dma_rx_completion); - init_completion(&mcspi_dma->dma_tx_completion); - - mcspi_dma->dma_rx = dma_request_chan(&master->dev, + mcspi_dma->dma_rx = dma_request_chan(mcspi->dev, mcspi_dma->dma_rx_ch_name); if (IS_ERR(mcspi_dma->dma_rx)) { ret = PTR_ERR(mcspi_dma->dma_rx); @@ -1006,7 +998,7 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) goto no_dma; } - mcspi_dma->dma_tx = dma_request_chan(&master->dev, + mcspi_dma->dma_tx = dma_request_chan(mcspi->dev, mcspi_dma->dma_tx_ch_name); if (IS_ERR(mcspi_dma->dma_tx)) { ret = PTR_ERR(mcspi_dma->dma_tx); @@ -1015,20 +1007,40 @@ static int omap2_mcspi_request_dma(struct spi_device *spi) mcspi_dma->dma_rx = NULL; } + init_completion(&mcspi_dma->dma_rx_completion); + init_completion(&mcspi_dma->dma_tx_completion); + no_dma: return ret; } +static void omap2_mcspi_release_dma(struct spi_master *master) +{ + struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + struct omap2_mcspi_dma *mcspi_dma; + int i; + + for (i = 0; i < master->num_chipselect; i++) { + mcspi_dma = &mcspi->dma_channels[i]; + + if (mcspi_dma->dma_rx) { + dma_release_channel(mcspi_dma->dma_rx); + mcspi_dma->dma_rx = NULL; + } + if (mcspi_dma->dma_tx) { + dma_release_channel(mcspi_dma->dma_tx); + mcspi_dma->dma_tx = NULL; + } + } +} + static int omap2_mcspi_setup(struct spi_device *spi) { int ret; struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master); struct omap2_mcspi_regs *ctx = &mcspi->ctx; - struct omap2_mcspi_dma *mcspi_dma; struct omap2_mcspi_cs *cs = spi->controller_state; - mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - if (!cs) { cs = kzalloc(sizeof *cs, GFP_KERNEL); if (!cs) @@ -1053,13 +1065,6 @@ static int omap2_mcspi_setup(struct spi_device *spi) } } - if (!mcspi_dma->dma_rx || !mcspi_dma->dma_tx) { - ret = omap2_mcspi_request_dma(spi); - if (ret) - dev_warn(&spi->dev, "not using DMA for McSPI (%d)\n", - ret); - } - ret = pm_runtime_get_sync(mcspi->dev); if (ret < 0) { pm_runtime_put_noidle(mcspi->dev); @@ -1076,12 +1081,8 @@ static int omap2_mcspi_setup(struct spi_device *spi) static void omap2_mcspi_cleanup(struct spi_device *spi) { - struct omap2_mcspi *mcspi; - struct omap2_mcspi_dma *mcspi_dma; struct omap2_mcspi_cs *cs; - mcspi = spi_master_get_devdata(spi->master); - if (spi->controller_state) { /* Unlink controller state from context save list */ cs = spi->controller_state; @@ -1090,19 +1091,6 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) kfree(cs); } - if (spi->chip_select < spi->master->num_chipselect) { - mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - - if (mcspi_dma->dma_rx) { - dma_release_channel(mcspi_dma->dma_rx); - mcspi_dma->dma_rx = NULL; - } - if (mcspi_dma->dma_tx) { - dma_release_channel(mcspi_dma->dma_tx); - mcspi_dma->dma_tx = NULL; - } - } - if (gpio_is_valid(spi->cs_gpio)) gpio_free(spi->cs_gpio); } @@ -1313,6 +1301,9 @@ static bool omap2_mcspi_can_dma(struct spi_master *master, if (spi_controller_is_slave(master)) return true; + master->dma_rx = mcspi_dma->dma_rx; + master->dma_tx = mcspi_dma->dma_tx; + return (xfer->len >= DMA_MIN_BYTES); } @@ -1475,6 +1466,11 @@ static int omap2_mcspi_probe(struct platform_device *pdev) for (i = 0; i < master->num_chipselect; i++) { sprintf(mcspi->dma_channels[i].dma_rx_ch_name, "rx%d", i); sprintf(mcspi->dma_channels[i].dma_tx_ch_name, "tx%d", i); + + status = omap2_mcspi_request_dma(mcspi, + &mcspi->dma_channels[i]); + if (status == -EPROBE_DEFER) + goto free_master; } status = platform_get_irq(pdev, 0); @@ -1512,6 +1508,7 @@ disable_pm: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); free_master: + omap2_mcspi_release_dma(master); spi_master_put(master); return status; } @@ -1521,6 +1518,8 @@ static int omap2_mcspi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct omap2_mcspi *mcspi = spi_master_get_devdata(master); + omap2_mcspi_release_dma(master); + pm_runtime_dont_use_autosuspend(mcspi->dev); pm_runtime_put_sync(mcspi->dev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 2fd843b18297..723145673206 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -68,6 +68,10 @@ MODULE_ALIAS("platform:pxa2xx-spi"); #define LPSS_CAPS_CS_EN_SHIFT 9 #define LPSS_CAPS_CS_EN_MASK (0xf << LPSS_CAPS_CS_EN_SHIFT) +#define LPSS_PRIV_CLOCK_GATE 0x38 +#define LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK 0x3 +#define LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_ON 0x3 + struct lpss_config { /* LPSS offset from drv_data->ioaddr */ unsigned offset; @@ -84,6 +88,8 @@ struct lpss_config { unsigned cs_sel_shift; unsigned cs_sel_mask; unsigned cs_num; + /* Quirks */ + unsigned cs_clk_stays_gated : 1; }; /* Keep these sorted with enum pxa_ssp_type */ @@ -154,6 +160,7 @@ static const struct lpss_config lpss_platforms[] = { .tx_threshold_hi = 56, .cs_sel_shift = 8, .cs_sel_mask = 3 << 8, + .cs_clk_stays_gated = true, }, }; @@ -381,6 +388,22 @@ static void lpss_ssp_cs_control(struct spi_device *spi, bool enable) else value |= LPSS_CS_CONTROL_CS_HIGH; __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value); + if (config->cs_clk_stays_gated) { + u32 clkgate; + + /* + * Changing CS alone when dynamic clock gating is on won't + * actually flip CS at that time. This ruins SPI transfers + * that specify delays, or have no data. Toggle the clock mode + * to force on briefly to poke the CS pin to move. + */ + clkgate = __lpss_ssp_read_priv(drv_data, LPSS_PRIV_CLOCK_GATE); + value = (clkgate & ~LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK) | + LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_ON; + + __lpss_ssp_write_priv(drv_data, LPSS_PRIV_CLOCK_GATE, value); + __lpss_ssp_write_priv(drv_data, LPSS_PRIV_CLOCK_GATE, clkgate); + } } static void cs_assert(struct spi_device *spi) diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 2f559e531100..fa8079fbea77 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -1217,6 +1217,11 @@ static int spi_qup_suspend(struct device *device) struct spi_qup *controller = spi_master_get_devdata(master); int ret; + if (pm_runtime_suspended(device)) { + ret = spi_qup_pm_resume_runtime(device); + if (ret) + return ret; + } ret = spi_master_suspend(master); if (ret) return ret; @@ -1225,10 +1230,8 @@ static int spi_qup_suspend(struct device *device) if (ret) return ret; - if (!pm_runtime_suspended(device)) { - clk_disable_unprepare(controller->cclk); - clk_disable_unprepare(controller->iclk); - } + clk_disable_unprepare(controller->cclk); + clk_disable_unprepare(controller->iclk); return 0; } diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 60c4de4e4485..7412a3042a8d 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -401,9 +401,6 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high) zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry); - /* Dummy generic FIFO entry */ - zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, 0x0); - /* Manually start the generic FIFO command */ zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) | diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 26b91ee0855d..c186d3a944cd 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2452,7 +2452,7 @@ int spi_register_controller(struct spi_controller *ctlr) if (ctlr->use_gpio_descriptors) { status = spi_get_gpio_descs(ctlr); if (status) - return status; + goto free_bus_id; /* * A controller using GPIO descriptors always * supports SPI_CS_HIGH if need be. @@ -2462,7 +2462,7 @@ int spi_register_controller(struct spi_controller *ctlr) /* Legacy code path for GPIOs from DT */ status = of_spi_get_gpio_numbers(ctlr); if (status) - return status; + goto free_bus_id; } } @@ -2470,17 +2470,14 @@ int spi_register_controller(struct spi_controller *ctlr) * Even if it's just one always-selected device, there must * be at least one chipselect. */ - if (!ctlr->num_chipselect) - return -EINVAL; + if (!ctlr->num_chipselect) { + status = -EINVAL; + goto free_bus_id; + } status = device_add(&ctlr->dev); - if (status < 0) { - /* free bus id */ - mutex_lock(&board_lock); - idr_remove(&spi_master_idr, ctlr->bus_num); - mutex_unlock(&board_lock); - goto done; - } + if (status < 0) + goto free_bus_id; dev_dbg(dev, "registered %s %s\n", spi_controller_is_slave(ctlr) ? "slave" : "master", dev_name(&ctlr->dev)); @@ -2496,11 +2493,7 @@ int spi_register_controller(struct spi_controller *ctlr) status = spi_controller_initialize_queue(ctlr); if (status) { device_del(&ctlr->dev); - /* free bus id */ - mutex_lock(&board_lock); - idr_remove(&spi_master_idr, ctlr->bus_num); - mutex_unlock(&board_lock); - goto done; + goto free_bus_id; } } /* add statistics */ @@ -2515,7 +2508,12 @@ int spi_register_controller(struct spi_controller *ctlr) /* Register devices from the device tree and ACPI */ of_register_spi_devices(ctlr); acpi_register_spi_devices(ctlr); -done: + return status; + +free_bus_id: + mutex_lock(&board_lock); + idr_remove(&spi_master_idr, ctlr->bus_num); + mutex_unlock(&board_lock); return status; } EXPORT_SYMBOL_GPL(spi_register_controller); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 3ea9d8a3e6e8..ab2c3848f5bf 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -394,6 +394,7 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) else retval = get_user(tmp, (u32 __user *)arg); if (retval == 0) { + struct spi_controller *ctlr = spi->controller; u32 save = spi->mode; if (tmp & ~SPI_MODE_MASK) { @@ -401,6 +402,10 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) break; } + if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && + ctlr->cs_gpiods[spi->chip_select]) + tmp |= SPI_CS_HIGH; + tmp |= spi->mode & ~SPI_MODE_MASK; spi->mode = (u16)tmp; retval = spi_setup(spi); diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 799f998d8085..a83911bafde0 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -62,6 +62,38 @@ static int ion_alloc_fd(size_t len, unsigned int heap_id_mask, return fd; } +size_t ion_query_heaps_kernel(struct ion_heap_data *hdata, size_t size) +{ + struct ion_device *dev = internal_dev; + size_t i = 0, num_heaps = 0; + struct ion_heap *heap; + + down_read(&dev->lock); + + // If size is 0, return without updating hdata. + if (size == 0) { + num_heaps = dev->heap_cnt; + goto out; + } + + plist_for_each_entry(heap, &dev->heaps, node) { + strncpy(hdata[i].name, heap->name, MAX_HEAP_NAME); + hdata[i].name[MAX_HEAP_NAME - 1] = '\0'; + hdata[i].type = heap->type; + hdata[i].heap_id = heap->id; + + i++; + if (i >= size) + break; + } + + num_heaps = i; +out: + up_read(&dev->lock); + return num_heaps; +} +EXPORT_SYMBOL_GPL(ion_query_heaps_kernel); + static int ion_query_heaps(struct ion_heap_query *query) { struct ion_device *dev = internal_dev; diff --git a/drivers/staging/greybus/tools/loopback_test.c b/drivers/staging/greybus/tools/loopback_test.c index ba6f905f26fa..69c6dce9be31 100644 --- a/drivers/staging/greybus/tools/loopback_test.c +++ b/drivers/staging/greybus/tools/loopback_test.c @@ -19,6 +19,7 @@ #include #define MAX_NUM_DEVICES 10 +#define MAX_SYSFS_PREFIX 0x80 #define MAX_SYSFS_PATH 0x200 #define CSV_MAX_LINE 0x1000 #define SYSFS_MAX_INT 0x20 @@ -67,7 +68,7 @@ struct loopback_results { }; struct loopback_device { - char name[MAX_SYSFS_PATH]; + char name[MAX_STR_LEN]; char sysfs_entry[MAX_SYSFS_PATH]; char debugfs_entry[MAX_SYSFS_PATH]; struct loopback_results results; @@ -93,8 +94,8 @@ struct loopback_test { int stop_all; int poll_count; char test_name[MAX_STR_LEN]; - char sysfs_prefix[MAX_SYSFS_PATH]; - char debugfs_prefix[MAX_SYSFS_PATH]; + char sysfs_prefix[MAX_SYSFS_PREFIX]; + char debugfs_prefix[MAX_SYSFS_PREFIX]; struct timespec poll_timeout; struct loopback_device devices[MAX_NUM_DEVICES]; struct loopback_results aggregate_results; @@ -637,7 +638,7 @@ baddir: static int open_poll_files(struct loopback_test *t) { struct loopback_device *dev; - char buf[MAX_STR_LEN]; + char buf[MAX_SYSFS_PATH + MAX_STR_LEN]; char dummy; int fds_idx = 0; int i; @@ -655,7 +656,7 @@ static int open_poll_files(struct loopback_test *t) goto err; } read(t->fds[fds_idx].fd, &dummy, 1); - t->fds[fds_idx].events = EPOLLERR|EPOLLPRI; + t->fds[fds_idx].events = POLLERR | POLLPRI; t->fds[fds_idx].revents = 0; fds_idx++; } @@ -748,7 +749,7 @@ static int wait_for_complete(struct loopback_test *t) } for (i = 0; i < t->poll_count; i++) { - if (t->fds[i].revents & EPOLLPRI) { + if (t->fds[i].revents & POLLPRI) { /* Dummy read to clear the event */ read(t->fds[i].fd, &dummy, 1); number_of_events++; @@ -907,10 +908,10 @@ int main(int argc, char *argv[]) t.iteration_max = atoi(optarg); break; case 'S': - snprintf(t.sysfs_prefix, MAX_SYSFS_PATH, "%s", optarg); + snprintf(t.sysfs_prefix, MAX_SYSFS_PREFIX, "%s", optarg); break; case 'D': - snprintf(t.debugfs_prefix, MAX_SYSFS_PATH, "%s", optarg); + snprintf(t.debugfs_prefix, MAX_SYSFS_PREFIX, "%s", optarg); break; case 'm': t.mask = atol(optarg); @@ -961,10 +962,10 @@ int main(int argc, char *argv[]) } if (!strcmp(t.sysfs_prefix, "")) - snprintf(t.sysfs_prefix, MAX_SYSFS_PATH, "%s", sysfs_prefix); + snprintf(t.sysfs_prefix, MAX_SYSFS_PREFIX, "%s", sysfs_prefix); if (!strcmp(t.debugfs_prefix, "")) - snprintf(t.debugfs_prefix, MAX_SYSFS_PATH, "%s", debugfs_prefix); + snprintf(t.debugfs_prefix, MAX_SYSFS_PREFIX, "%s", debugfs_prefix); ret = find_loopback_devices(&t); if (ret) diff --git a/drivers/staging/kpc2000/kpc2000/core.c b/drivers/staging/kpc2000/kpc2000/core.c index 0a23727d0dc3..871441658f0e 100644 --- a/drivers/staging/kpc2000/kpc2000/core.c +++ b/drivers/staging/kpc2000/kpc2000/core.c @@ -110,10 +110,10 @@ static ssize_t cpld_reconfigure(struct device *dev, const char *buf, size_t count) { struct kp2000_device *pcard = dev_get_drvdata(dev); - long wr_val; + unsigned long wr_val; int rv; - rv = kstrtol(buf, 0, &wr_val); + rv = kstrtoul(buf, 0, &wr_val); if (rv < 0) return rv; if (wr_val > 7) diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 6d9d41170832..32e5966ba5c5 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -553,13 +553,13 @@ static int hantro_attach_func(struct hantro_dev *vpu, goto err_rel_entity1; /* Connect the three entities */ - ret = media_create_pad_link(&func->vdev.entity, 0, &func->proc, 1, + ret = media_create_pad_link(&func->vdev.entity, 0, &func->proc, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) goto err_rel_entity2; - ret = media_create_pad_link(&func->proc, 0, &func->sink, 0, + ret = media_create_pad_link(&func->proc, 1, &func->sink, 0, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret) diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index b5d42f411dd8..f7f09c0d273f 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -32,12 +32,14 @@ static const struct usb_device_id rtw_usb_id_tbl[] = { /****** 8188EUS ********/ {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */ {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */ + {USB_DEVICE(0x0B05, 0x18F0)}, /* ASUS USB-N10 Nano B1 */ {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */ {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */ {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */ {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */ {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */ {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */ + {USB_DEVICE(0x2C4E, 0x0102)}, /* MERCUSYS MW150US v2 */ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */ {} /* Terminating entry */ diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 488f2539aa9a..81ecfd1a200d 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -561,7 +561,7 @@ static u_long get_word(struct vc_data *vc) return 0; } else if (tmpx < vc->vc_cols - 2 && (ch == SPACE || ch == 0 || (ch < 0x100 && IS_WDLM(ch))) && - get_char(vc, (u_short *)&tmp_pos + 1, &temp) > SPACE) { + get_char(vc, (u_short *)tmp_pos + 1, &temp) > SPACE) { tmp_pos += 2; tmpx++; } else { diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index a8b4d0c5ab7e..032f3264fba1 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -51,9 +51,7 @@ static void __speakup_set_selection(struct work_struct *work) goto unref; } - console_lock(); set_selection_kernel(&sel, tty); - console_unlock(); unref: tty_kref_put(tty); diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 28d372a0663a..e29c14e0ed49 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -3374,6 +3374,8 @@ static void hfa384x_int_rxmonitor(struct wlandevice *wlandev, WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN)) { pr_debug("overlen frm: len=%zd\n", skblen - sizeof(struct p80211_caphdr)); + + return; } skb = dev_alloc_skb(skblen); diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index b5ba176004c1..d8d86761b790 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -180,6 +180,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) cancel_work_sync(&hw->link_bh); cancel_work_sync(&hw->commsqual_bh); + cancel_work_sync(&hw->usb_work); /* Now we complete any outstanding commands * and tell everyone who is waiting for their diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index d7dda2efa257..c324074fc67c 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -439,4 +439,11 @@ config UNIPHIER_THERMAL Enable this to plug in UniPhier on-chip PVT thermal driver into the thermal framework. The driver supports CPU thermal zone temperature reporting and a couple of trip points. + +config SPRD_THERMAL + tristate "Temperature sensor on Spreadtrum SoCs" + depends on ARCH_SPRD || COMPILE_TEST + help + Support for the Spreadtrum thermal sensor driver in the Linux thermal + framework. endif diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 191ce99e4953..1db917aa39d5 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o obj-$(CONFIG_THERMAL_TSENS) += msm-tsens-driver.o msm-tsens-driver-objs := msm-tsens.o tsens2xxx.o tsens-dbg.o tsens-mtc.o tsens1xxx.o tsens-calib.o +obj-$(CONFIG_SPRD_THERMAL) += sprd_thermal.o diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c new file mode 100644 index 000000000000..a340374e8c51 --- /dev/null +++ b/drivers/thermal/sprd_thermal.c @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2020 Spreadtrum Communications Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPRD_THM_CTL 0x0 +#define SPRD_THM_INT_EN 0x4 +#define SPRD_THM_INT_STS 0x8 +#define SPRD_THM_INT_RAW_STS 0xc +#define SPRD_THM_DET_PERIOD 0x10 +#define SPRD_THM_INT_CLR 0x14 +#define SPRD_THM_INT_CLR_ST 0x18 +#define SPRD_THM_MON_PERIOD 0x4c +#define SPRD_THM_MON_CTL 0x50 +#define SPRD_THM_INTERNAL_STS1 0x54 +#define SPRD_THM_RAW_READ_MSK 0x3ff + +#define SPRD_THM_OFFSET(id) ((id) * 0x4) +#define SPRD_THM_TEMP(id) (SPRD_THM_OFFSET(id) + 0x5c) +#define SPRD_THM_THRES(id) (SPRD_THM_OFFSET(id) + 0x2c) + +#define SPRD_THM_SEN(id) BIT((id) + 2) +#define SPRD_THM_SEN_OVERHEAT_EN(id) BIT((id) + 8) +#define SPRD_THM_SEN_OVERHEAT_ALARM_EN(id) BIT((id) + 0) + +/* bits definitions for register THM_CTL */ +#define SPRD_THM_SET_RDY_ST BIT(13) +#define SPRD_THM_SET_RDY BIT(12) +#define SPRD_THM_MON_EN BIT(1) +#define SPRD_THM_EN BIT(0) + +/* bits definitions for register THM_INT_CTL */ +#define SPRD_THM_BIT_INT_EN BIT(26) +#define SPRD_THM_OVERHEAT_EN BIT(25) +#define SPRD_THM_OTP_TRIP_SHIFT 10 + +/* bits definitions for register SPRD_THM_INTERNAL_STS1 */ +#define SPRD_THM_TEMPER_RDY BIT(0) + +#define SPRD_THM_DET_PERIOD_DATA 0x800 +#define SPRD_THM_DET_PERIOD_MASK GENMASK(19, 0) +#define SPRD_THM_MON_MODE 0x7 +#define SPRD_THM_MON_MODE_MASK GENMASK(3, 0) +#define SPRD_THM_MON_PERIOD_DATA 0x10 +#define SPRD_THM_MON_PERIOD_MASK GENMASK(15, 0) +#define SPRD_THM_THRES_MASK GENMASK(19, 0) +#define SPRD_THM_INT_CLR_MASK GENMASK(24, 0) + +/* thermal sensor calibration parameters */ +#define SPRD_THM_TEMP_LOW -40000 +#define SPRD_THM_TEMP_HIGH 120000 +#define SPRD_THM_OTP_TEMP 120000 +#define SPRD_THM_HOT_TEMP 75000 +#define SPRD_THM_RAW_DATA_LOW 0 +#define SPRD_THM_RAW_DATA_HIGH 1000 +#define SPRD_THM_SEN_NUM 8 +#define SPRD_THM_DT_OFFSET 24 +#define SPRD_THM_RATION_OFFSET 17 +#define SPRD_THM_RATION_SIGN 16 + +#define SPRD_THM_RDYST_POLLING_TIME 10 +#define SPRD_THM_RDYST_TIMEOUT 700 +#define SPRD_THM_TEMP_READY_POLL_TIME 10000 +#define SPRD_THM_TEMP_READY_TIMEOUT 600000 +#define SPRD_THM_MAX_SENSOR 8 + +struct sprd_thermal_sensor { + struct thermal_zone_device *tzd; + struct sprd_thermal_data *data; + struct device *dev; + int cal_slope; + int cal_offset; + int id; +}; + +struct sprd_thermal_data { + const struct sprd_thm_variant_data *var_data; + struct sprd_thermal_sensor *sensor[SPRD_THM_MAX_SENSOR]; + struct clk *clk; + void __iomem *base; + u32 ratio_off; + int ratio_sign; + int nr_sensors; +}; + +/* + * The conversion between ADC and temperature is based on linear relationship, + * and use idea_k to specify the slope and ideal_b to specify the offset. + * + * Since different Spreadtrum SoCs have different ideal_k and ideal_b, + * we should save ideal_k and ideal_b in the device data structure. + */ +struct sprd_thm_variant_data { + u32 ideal_k; + u32 ideal_b; +}; + +static const struct sprd_thm_variant_data ums512_data = { + .ideal_k = 262, + .ideal_b = 66400, +}; + +static inline void sprd_thm_update_bits(void __iomem *reg, u32 mask, u32 val) +{ + u32 tmp, orig; + + orig = readl(reg); + tmp = orig & ~mask; + tmp |= val & mask; + writel(tmp, reg); +} + +static int sprd_thm_cal_read(struct device_node *np, const char *cell_id, + u32 *val) +{ + struct nvmem_cell *cell; + void *buf; + size_t len; + + cell = of_nvmem_cell_get(np, cell_id); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + buf = nvmem_cell_read(cell, &len); + nvmem_cell_put(cell); + if (IS_ERR(buf)) + return PTR_ERR(buf); + + if (len > sizeof(u32)) { + kfree(buf); + return -EINVAL; + } + + memcpy(val, buf, len); + + kfree(buf); + return 0; +} + +static int sprd_thm_sensor_calibration(struct device_node *np, + struct sprd_thermal_data *thm, + struct sprd_thermal_sensor *sen) +{ + int ret; + /* + * According to thermal datasheet, the default calibration offset is 64, + * and the default ratio is 1000. + */ + int dt_offset = 64, ratio = 1000; + + ret = sprd_thm_cal_read(np, "sen_delta_cal", &dt_offset); + if (ret) + return ret; + + ratio += thm->ratio_sign * thm->ratio_off; + + /* + * According to the ideal slope K and ideal offset B, combined with + * calibration value of thermal from efuse, then calibrate the real + * slope k and offset b: + * k_cal = (k * ratio) / 1000. + * b_cal = b + (dt_offset - 64) * 500. + */ + sen->cal_slope = (thm->var_data->ideal_k * ratio) / 1000; + sen->cal_offset = thm->var_data->ideal_b + (dt_offset - 128) * 250; + + return 0; +} + +static int sprd_thm_rawdata_to_temp(struct sprd_thermal_sensor *sen, + u32 rawdata) +{ + clamp(rawdata, (u32)SPRD_THM_RAW_DATA_LOW, (u32)SPRD_THM_RAW_DATA_HIGH); + + /* + * According to the thermal datasheet, the formula of converting + * adc value to the temperature value should be: + * T_final = k_cal * x - b_cal. + */ + return sen->cal_slope * rawdata - sen->cal_offset; +} + +static int sprd_thm_temp_to_rawdata(int temp, struct sprd_thermal_sensor *sen) +{ + u32 val; + + clamp(temp, (int)SPRD_THM_TEMP_LOW, (int)SPRD_THM_TEMP_HIGH); + + /* + * According to the thermal datasheet, the formula of converting + * adc value to the temperature value should be: + * T_final = k_cal * x - b_cal. + */ + val = (temp + sen->cal_offset) / sen->cal_slope; + + return clamp(val, val, (u32)(SPRD_THM_RAW_DATA_HIGH - 1)); +} + +static int sprd_thm_read_temp(void *devdata, int *temp) +{ + struct sprd_thermal_sensor *sen = devdata; + u32 data; + + data = readl(sen->data->base + SPRD_THM_TEMP(sen->id)) & + SPRD_THM_RAW_READ_MSK; + + *temp = sprd_thm_rawdata_to_temp(sen, data); + + return 0; +} + +static const struct thermal_zone_of_device_ops sprd_thm_ops = { + .get_temp = sprd_thm_read_temp, +}; + +static int sprd_thm_poll_ready_status(struct sprd_thermal_data *thm) +{ + u32 val; + int ret; + + /* + * Wait for thermal ready status before configuring thermal parameters. + */ + ret = readl_poll_timeout(thm->base + SPRD_THM_CTL, val, + !(val & SPRD_THM_SET_RDY_ST), + SPRD_THM_RDYST_POLLING_TIME, + SPRD_THM_RDYST_TIMEOUT); + if (ret) + return ret; + + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_MON_EN, + SPRD_THM_MON_EN); + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_SET_RDY, + SPRD_THM_SET_RDY); + return 0; +} + +static int sprd_thm_wait_temp_ready(struct sprd_thermal_data *thm) +{ + u32 val; + + /* Wait for first temperature data ready before reading temperature */ + return readl_poll_timeout(thm->base + SPRD_THM_INTERNAL_STS1, val, + !(val & SPRD_THM_TEMPER_RDY), + SPRD_THM_TEMP_READY_POLL_TIME, + SPRD_THM_TEMP_READY_TIMEOUT); +} + +static int sprd_thm_set_ready(struct sprd_thermal_data *thm) +{ + int ret; + + ret = sprd_thm_poll_ready_status(thm); + if (ret) + return ret; + + /* + * Clear interrupt status, enable thermal interrupt and enable thermal. + * + * The SPRD thermal controller integrates a hardware interrupt signal, + * which means if the temperature is overheat, it will generate an + * interrupt and notify the event to PMIC automatically to shutdown the + * system. So here we should enable the interrupt bits, though we have + * not registered an irq handler. + */ + writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR); + sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN, + SPRD_THM_BIT_INT_EN, SPRD_THM_BIT_INT_EN); + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, + SPRD_THM_EN, SPRD_THM_EN); + return 0; +} + +static void sprd_thm_sensor_init(struct sprd_thermal_data *thm, + struct sprd_thermal_sensor *sen) +{ + u32 otp_rawdata, hot_rawdata; + + otp_rawdata = sprd_thm_temp_to_rawdata(SPRD_THM_OTP_TEMP, sen); + hot_rawdata = sprd_thm_temp_to_rawdata(SPRD_THM_HOT_TEMP, sen); + + /* Enable the sensor' overheat temperature protection interrupt */ + sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN, + SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id), + SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id)); + + /* Set the sensor' overheat and hot threshold temperature */ + sprd_thm_update_bits(thm->base + SPRD_THM_THRES(sen->id), + SPRD_THM_THRES_MASK, + (otp_rawdata << SPRD_THM_OTP_TRIP_SHIFT) | + hot_rawdata); + + /* Enable the corresponding sensor */ + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, SPRD_THM_SEN(sen->id), + SPRD_THM_SEN(sen->id)); +} + +static void sprd_thm_para_config(struct sprd_thermal_data *thm) +{ + /* Set the period of two valid temperature detection action */ + sprd_thm_update_bits(thm->base + SPRD_THM_DET_PERIOD, + SPRD_THM_DET_PERIOD_MASK, SPRD_THM_DET_PERIOD); + + /* Set the sensors' monitor mode */ + sprd_thm_update_bits(thm->base + SPRD_THM_MON_CTL, + SPRD_THM_MON_MODE_MASK, SPRD_THM_MON_MODE); + + /* Set the sensors' monitor period */ + sprd_thm_update_bits(thm->base + SPRD_THM_MON_PERIOD, + SPRD_THM_MON_PERIOD_MASK, SPRD_THM_MON_PERIOD); +} + +static void sprd_thm_toggle_sensor(struct sprd_thermal_sensor *sen, bool on) +{ + struct thermal_zone_device *tzd = sen->tzd; + + tzd->ops->set_mode(tzd, + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); +} + +static int sprd_thm_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *sen_child; + struct sprd_thermal_data *thm; + struct sprd_thermal_sensor *sen; + const struct sprd_thm_variant_data *pdata; + int ret, i; + u32 val; + + pdata = of_device_get_match_data(&pdev->dev); + if (!pdata) { + dev_err(&pdev->dev, "No matching driver data found\n"); + return -EINVAL; + } + + thm = devm_kzalloc(&pdev->dev, sizeof(*thm), GFP_KERNEL); + if (!thm) + return -ENOMEM; + + thm->var_data = pdata; + thm->base = devm_platform_ioremap_resource(pdev, 0); + if (!thm->base) + return -ENOMEM; + + thm->nr_sensors = of_get_child_count(np); + if (thm->nr_sensors == 0 || thm->nr_sensors > SPRD_THM_MAX_SENSOR) { + dev_err(&pdev->dev, "incorrect sensor count\n"); + return -EINVAL; + } + + thm->clk = devm_clk_get(&pdev->dev, "enable"); + if (IS_ERR(thm->clk)) { + dev_err(&pdev->dev, "failed to get enable clock\n"); + return PTR_ERR(thm->clk); + } + + ret = clk_prepare_enable(thm->clk); + if (ret) + return ret; + + sprd_thm_para_config(thm); + + ret = sprd_thm_cal_read(np, "thm_sign_cal", &val); + if (ret) + goto disable_clk; + + if (val > 0) + thm->ratio_sign = -1; + else + thm->ratio_sign = 1; + + ret = sprd_thm_cal_read(np, "thm_ratio_cal", &thm->ratio_off); + if (ret) + goto disable_clk; + + for_each_child_of_node(np, sen_child) { + sen = devm_kzalloc(&pdev->dev, sizeof(*sen), GFP_KERNEL); + if (!sen) { + ret = -ENOMEM; + goto disable_clk; + } + + sen->data = thm; + sen->dev = &pdev->dev; + + ret = of_property_read_u32(sen_child, "reg", &sen->id); + if (ret) { + dev_err(&pdev->dev, "get sensor reg failed"); + goto disable_clk; + } + + ret = sprd_thm_sensor_calibration(sen_child, thm, sen); + if (ret) { + dev_err(&pdev->dev, "efuse cal analysis failed"); + goto disable_clk; + } + + sprd_thm_sensor_init(thm, sen); + + sen->tzd = devm_thermal_zone_of_sensor_register(sen->dev, + sen->id, + sen, + &sprd_thm_ops); + if (IS_ERR(sen->tzd)) { + dev_err(&pdev->dev, "register thermal zone failed %d\n", + sen->id); + ret = PTR_ERR(sen->tzd); + goto disable_clk; + } + + thm->sensor[sen->id] = sen; + } + + ret = sprd_thm_set_ready(thm); + if (ret) + goto disable_clk; + + ret = sprd_thm_wait_temp_ready(thm); + if (ret) + goto disable_clk; + + for (i = 0; i < thm->nr_sensors; i++) + sprd_thm_toggle_sensor(thm->sensor[i], true); + + platform_set_drvdata(pdev, thm); + return 0; + +disable_clk: + clk_disable_unprepare(thm->clk); + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static void sprd_thm_hw_suspend(struct sprd_thermal_data *thm) +{ + int i; + + for (i = 0; i < thm->nr_sensors; i++) { + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, + SPRD_THM_SEN(thm->sensor[i]->id), 0); + } + + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, + SPRD_THM_EN, 0x0); +} + +static int sprd_thm_suspend(struct device *dev) +{ + struct sprd_thermal_data *thm = dev_get_drvdata(dev); + int i; + + for (i = 0; i < thm->nr_sensors; i++) + sprd_thm_toggle_sensor(thm->sensor[i], false); + + sprd_thm_hw_suspend(thm); + clk_disable_unprepare(thm->clk); + + return 0; +} + +static int sprd_thm_hw_resume(struct sprd_thermal_data *thm) +{ + int ret, i; + + for (i = 0; i < thm->nr_sensors; i++) { + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, + SPRD_THM_SEN(thm->sensor[i]->id), + SPRD_THM_SEN(thm->sensor[i]->id)); + } + + ret = sprd_thm_poll_ready_status(thm); + if (ret) + return ret; + + writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR); + sprd_thm_update_bits(thm->base + SPRD_THM_CTL, + SPRD_THM_EN, SPRD_THM_EN); + return sprd_thm_wait_temp_ready(thm); +} + +static int sprd_thm_resume(struct device *dev) +{ + struct sprd_thermal_data *thm = dev_get_drvdata(dev); + int ret, i; + + ret = clk_prepare_enable(thm->clk); + if (ret) + return ret; + + ret = sprd_thm_hw_resume(thm); + if (ret) + goto disable_clk; + + for (i = 0; i < thm->nr_sensors; i++) + sprd_thm_toggle_sensor(thm->sensor[i], true); + + return 0; + +disable_clk: + clk_disable_unprepare(thm->clk); + return ret; +} +#endif + +static int sprd_thm_remove(struct platform_device *pdev) +{ + struct sprd_thermal_data *thm = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < thm->nr_sensors; i++) { + sprd_thm_toggle_sensor(thm->sensor[i], false); + devm_thermal_zone_of_sensor_unregister(&pdev->dev, + thm->sensor[i]->tzd); + } + + clk_disable_unprepare(thm->clk); + return 0; +} + +static const struct of_device_id sprd_thermal_of_match[] = { + { .compatible = "sprd,ums512-thermal", .data = &ums512_data }, + { }, +}; + +static const struct dev_pm_ops sprd_thermal_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(sprd_thm_suspend, sprd_thm_resume) +}; + +static struct platform_driver sprd_thermal_driver = { + .probe = sprd_thm_probe, + .remove = sprd_thm_remove, + .driver = { + .name = "sprd-thermal", + .pm = &sprd_thermal_pm_ops, + .of_match_table = sprd_thermal_of_match, + }, +}; + +module_platform_driver(sprd_thermal_driver); + +MODULE_AUTHOR("Freeman Liu "); +MODULE_DESCRIPTION("Spreadtrum thermal driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 3d828e2d891c..67bb0a0b730e 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c @@ -279,11 +279,6 @@ struct device *serdev_tty_port_register(struct tty_port *port, if (!port || !drv || !parent) return ERR_PTR(-ENODEV); - if (port->console) { - /* can't convert tty's that are already in use */ - return ERR_PTR(-ENODEV); - } - ctrl = serdev_controller_alloc(parent, sizeof(struct serport)); if (!ctrl) return ERR_PTR(-ENOMEM); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 597eb9d16f21..e1268646ee56 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -25,6 +25,14 @@ #include "8250.h" +#define PCI_DEVICE_ID_ACCES_COM_2S 0x1052 +#define PCI_DEVICE_ID_ACCES_COM_4S 0x105d +#define PCI_DEVICE_ID_ACCES_COM_8S 0x106c +#define PCI_DEVICE_ID_ACCES_COM232_8 0x10a8 +#define PCI_DEVICE_ID_ACCES_COM_2SM 0x10d2 +#define PCI_DEVICE_ID_ACCES_COM_4SM 0x10db +#define PCI_DEVICE_ID_ACCES_COM_8SM 0x10ea + #define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002 #define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004 #define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a @@ -658,6 +666,22 @@ static int __maybe_unused exar_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume); +static const struct exar8250_board acces_com_2x = { + .num_ports = 2, + .setup = pci_xr17c154_setup, +}; + +static const struct exar8250_board acces_com_4x = { + .num_ports = 4, + .setup = pci_xr17c154_setup, +}; + +static const struct exar8250_board acces_com_8x = { + .num_ports = 8, + .setup = pci_xr17c154_setup, +}; + + static const struct exar8250_board pbn_fastcom335_2 = { .num_ports = 2, .setup = pci_fastcom335_setup, @@ -726,6 +750,15 @@ static const struct exar8250_board pbn_exar_XR17V8358 = { } static const struct pci_device_id exar_pci_tbl[] = { + EXAR_DEVICE(ACCESSIO, ACCES_COM_2S, acces_com_2x), + EXAR_DEVICE(ACCESSIO, ACCES_COM_4S, acces_com_4x), + EXAR_DEVICE(ACCESSIO, ACCES_COM_8S, acces_com_8x), + EXAR_DEVICE(ACCESSIO, ACCES_COM232_8, acces_com_8x), + EXAR_DEVICE(ACCESSIO, ACCES_COM_2SM, acces_com_2x), + EXAR_DEVICE(ACCESSIO, ACCES_COM_4SM, acces_com_4x), + EXAR_DEVICE(ACCESSIO, ACCES_COM_8SM, acces_com_8x), + + CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect), CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect), CONNECT_DEVICE(XR17C158, UART_8_232, pbn_connect), diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index 3bdd56a1021b..ea12f10610b6 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -286,6 +286,10 @@ static void ar933x_uart_set_termios(struct uart_port *port, ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, AR933X_UART_CS_HOST_INT_EN); + /* enable RX and TX ready overide */ + ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, + AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE); + /* reenable the UART */ ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S, @@ -418,6 +422,10 @@ static int ar933x_uart_startup(struct uart_port *port) ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, AR933X_UART_CS_HOST_INT_EN); + /* enable RX and TX ready overide */ + ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, + AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE); + /* Enable RX interrupts */ up->ier = AR933X_UART_INT_RX_VALID; ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 3f64b08f50ef..d2fc050a3445 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -268,6 +268,7 @@ struct lpuart_port { int rx_dma_rng_buf_len; unsigned int dma_tx_nents; wait_queue_head_t dma_wait; + bool id_allocated; }; struct lpuart_soc_data { @@ -2382,19 +2383,6 @@ static int lpuart_probe(struct platform_device *pdev) if (!sport) return -ENOMEM; - ret = of_alias_get_id(np, "serial"); - if (ret < 0) { - ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL); - if (ret < 0) { - dev_err(&pdev->dev, "port line is full, add device failed\n"); - return ret; - } - } - if (ret >= ARRAY_SIZE(lpuart_ports)) { - dev_err(&pdev->dev, "serial%d out of range\n", ret); - return -EINVAL; - } - sport->port.line = ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); sport->port.membase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(sport->port.membase)) @@ -2435,9 +2423,25 @@ static int lpuart_probe(struct platform_device *pdev) } } + ret = of_alias_get_id(np, "serial"); + if (ret < 0) { + ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL); + if (ret < 0) { + dev_err(&pdev->dev, "port line is full, add device failed\n"); + return ret; + } + sport->id_allocated = true; + } + if (ret >= ARRAY_SIZE(lpuart_ports)) { + dev_err(&pdev->dev, "serial%d out of range\n", ret); + ret = -EINVAL; + goto failed_out_of_range; + } + sport->port.line = ret; + ret = lpuart_enable_clks(sport); if (ret) - return ret; + goto failed_clock_enable; sport->port.uartclk = lpuart_get_baud_clk_rate(sport); lpuart_ports[sport->port.line] = sport; @@ -2487,6 +2491,10 @@ static int lpuart_probe(struct platform_device *pdev) failed_attach_port: failed_irq_request: lpuart_disable_clks(sport); +failed_clock_enable: +failed_out_of_range: + if (sport->id_allocated) + ida_simple_remove(&fsl_lpuart_ida, sport->port.line); return ret; } @@ -2496,7 +2504,8 @@ static int lpuart_remove(struct platform_device *pdev) uart_remove_one_port(&lpuart_reg, &sport->port); - ida_simple_remove(&fsl_lpuart_ida, sport->port.line); + if (sport->id_allocated) + ida_simple_remove(&fsl_lpuart_ida, sport->port.line); lpuart_disable_clks(sport); diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index c12a12556339..4e9a590712cb 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -851,7 +851,7 @@ static int mvebu_uart_probe(struct platform_device *pdev) port->membase = devm_ioremap_resource(&pdev->dev, reg); if (IS_ERR(port->membase)) - return -PTR_ERR(port->membase); + return PTR_ERR(port->membase); mvuart = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_uart), GFP_KERNEL); diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index f60a59d9bf27..685041d14e01 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -1136,14 +1136,13 @@ static int sprd_remove(struct platform_device *dev) if (sup) { uart_remove_one_port(&sprd_uart_driver, &sup->port); sprd_port[sup->port.line] = NULL; + sprd_rx_free_buf(sup); sprd_ports_num--; } if (!sprd_ports_num) uart_unregister_driver(&sprd_uart_driver); - sprd_rx_free_buf(sup); - return 0; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 802c1210558f..36c1c59cc72a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2731,9 +2731,11 @@ static int compat_tty_tiocgserial(struct tty_struct *tty, struct serial_struct32 v32; struct serial_struct v; int err; - memset(&v, 0, sizeof(struct serial_struct)); - if (!tty->ops->set_serial) + memset(&v, 0, sizeof(v)); + memset(&v32, 0, sizeof(v32)); + + if (!tty->ops->get_serial) return -ENOTTY; err = tty->ops->get_serial(tty, &v); if (!err) { diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 44d974d4159f..7556139cd0da 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ static volatile int sel_start = -1; /* cleared by clear_selection */ static int sel_end; static int sel_buffer_lth; static char *sel_buffer; +static DEFINE_MUTEX(sel_lock); /* clear_selection, highlight and highlight_pointer can be called from interrupt (via scrollback/front) */ @@ -86,6 +88,11 @@ void clear_selection(void) } EXPORT_SYMBOL_GPL(clear_selection); +bool vc_is_sel(struct vc_data *vc) +{ + return vc == sel_cons; +} + /* * User settable table: what characters are to be considered alphabetic? * 128 bits. Locked by the console lock. @@ -179,14 +186,14 @@ int set_selection_user(const struct tiocl_selection __user *sel, return set_selection_kernel(&v, tty); } -int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty) +static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty) { struct vc_data *vc = vc_cons[fg_console].d; int new_sel_start, new_sel_end, spc; char *bp, *obp; int i, ps, pe, multiplier; u32 c; - int mode; + int mode, ret = 0; poke_blanked_console(); @@ -334,7 +341,21 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty) } } sel_buffer_lth = bp - sel_buffer; - return 0; + + return ret; +} + +int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty) +{ + int ret; + + mutex_lock(&sel_lock); + console_lock(); + ret = __set_selection_kernel(v, tty); + console_unlock(); + mutex_unlock(&sel_lock); + + return ret; } EXPORT_SYMBOL_GPL(set_selection_kernel); @@ -364,6 +385,7 @@ int paste_selection(struct tty_struct *tty) tty_buffer_lock_exclusive(&vc->port); add_wait_queue(&vc->paste_wait, &wait); + mutex_lock(&sel_lock); while (sel_buffer && sel_buffer_lth > pasted) { set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { @@ -371,7 +393,9 @@ int paste_selection(struct tty_struct *tty) break; } if (tty_throttled(tty)) { + mutex_unlock(&sel_lock); schedule(); + mutex_lock(&sel_lock); continue; } __set_current_state(TASK_RUNNING); @@ -380,6 +404,7 @@ int paste_selection(struct tty_struct *tty) count); pasted += count; } + mutex_unlock(&sel_lock); remove_wait_queue(&vc->paste_wait, &wait); __set_current_state(TASK_RUNNING); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 3b4ccc2a30c1..fa9433e6cdc7 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -890,8 +890,9 @@ static void hide_softcursor(struct vc_data *vc) static void hide_cursor(struct vc_data *vc) { - if (vc == sel_cons) + if (vc_is_sel(vc)) clear_selection(); + vc->vc_sw->con_cursor(vc, CM_ERASE); hide_softcursor(vc); } @@ -901,7 +902,7 @@ static void set_cursor(struct vc_data *vc) if (!con_is_fg(vc) || console_blanked || vc->vc_mode == KD_GRAPHICS) return; if (vc->vc_deccm) { - if (vc == sel_cons) + if (vc_is_sel(vc)) clear_selection(); add_softcursor(vc); if ((vc->vc_cursor_type & 0x0f) != 1) @@ -1074,6 +1075,17 @@ static void visual_deinit(struct vc_data *vc) module_put(vc->vc_sw->owner); } +static void vc_port_destruct(struct tty_port *port) +{ + struct vc_data *vc = container_of(port, struct vc_data, port); + + kfree(vc); +} + +static const struct tty_port_operations vc_port_ops = { + .destruct = vc_port_destruct, +}; + int vc_allocate(unsigned int currcons) /* return 0 on success */ { struct vt_notifier_param param; @@ -1099,6 +1111,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ vc_cons[currcons].d = vc; tty_port_init(&vc->port); + vc->port.ops = &vc_port_ops; INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); visual_init(vc, currcons, 1); @@ -1207,7 +1220,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, } } - if (vc == sel_cons) + if (vc_is_sel(vc)) clear_selection(); old_rows = vc->vc_rows; @@ -3046,10 +3059,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) switch (type) { case TIOCL_SETSEL: - console_lock(); ret = set_selection_user((struct tiocl_selection __user *)(p+1), tty); - console_unlock(); break; case TIOCL_PASTESEL: ret = paste_selection(tty); @@ -3255,6 +3266,7 @@ static int con_install(struct tty_driver *driver, struct tty_struct *tty) tty->driver_data = vc; vc->port.tty = tty; + tty_port_get(&vc->port); if (!tty->winsize.ws_row && !tty->winsize.ws_col) { tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; @@ -3290,6 +3302,13 @@ static void con_shutdown(struct tty_struct *tty) console_unlock(); } +static void con_cleanup(struct tty_struct *tty) +{ + struct vc_data *vc = tty->driver_data; + + tty_port_put(&vc->port); +} + static int default_color = 7; /* white */ static int default_italic_color = 2; // green (ASCII) static int default_underline_color = 3; // cyan (ASCII) @@ -3414,7 +3433,8 @@ static const struct tty_operations con_ops = { .throttle = con_throttle, .unthrottle = con_unthrottle, .resize = vt_resize, - .shutdown = con_shutdown + .shutdown = con_shutdown, + .cleanup = con_cleanup, }; static struct cdev vc0_cdev; diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index ee6c91ef1f6c..daf61c28ba76 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -39,11 +39,32 @@ #include #include -char vt_dont_switch; -extern struct tty_driver *console_driver; +bool vt_dont_switch; -#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count) -#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons) +static inline bool vt_in_use(unsigned int i) +{ + const struct vc_data *vc = vc_cons[i].d; + + /* + * console_lock must be held to prevent the vc from being deallocated + * while we're checking whether it's in-use. + */ + WARN_CONSOLE_UNLOCKED(); + + return vc && kref_read(&vc->port.kref) > 1; +} + +static inline bool vt_busy(int i) +{ + if (vt_in_use(i)) + return true; + if (i == fg_console) + return true; + if (vc_is_sel(vc_cons[i].d)) + return true; + + return false; +} /* * Console (vt and kd) routines, as defined by USL SVR4 manual, and by @@ -289,16 +310,14 @@ static int vt_disallocate(unsigned int vc_num) int ret = 0; console_lock(); - if (VT_BUSY(vc_num)) + if (vt_busy(vc_num)) ret = -EBUSY; else if (vc_num) vc = vc_deallocate(vc_num); console_unlock(); - if (vc && vc_num >= MIN_NR_CONSOLES) { - tty_port_destroy(&vc->port); - kfree(vc); - } + if (vc && vc_num >= MIN_NR_CONSOLES) + tty_port_put(&vc->port); return ret; } @@ -311,17 +330,15 @@ static void vt_disallocate_all(void) console_lock(); for (i = 1; i < MAX_NR_CONSOLES; i++) - if (!VT_BUSY(i)) + if (!vt_busy(i)) vc[i] = vc_deallocate(i); else vc[i] = NULL; console_unlock(); for (i = 1; i < MAX_NR_CONSOLES; i++) { - if (vc[i] && i >= MIN_NR_CONSOLES) { - tty_port_destroy(&vc[i]->port); - kfree(vc[i]); - } + if (vc[i] && i >= MIN_NR_CONSOLES) + tty_port_put(&vc[i]->port); } } @@ -335,22 +352,13 @@ int vt_ioctl(struct tty_struct *tty, { struct vc_data *vc = tty->driver_data; struct console_font_op op; /* used in multiple places here */ - unsigned int console; + unsigned int console = vc->vc_num; unsigned char ucval; unsigned int uival; void __user *up = (void __user *)arg; int i, perm; int ret = 0; - console = vc->vc_num; - - - if (!vc_cons_allocated(console)) { /* impossible? */ - ret = -ENOIOCTLCMD; - goto out; - } - - /* * To have permissions to do most of the vt ioctls, we either have * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. @@ -641,15 +649,16 @@ int vt_ioctl(struct tty_struct *tty, struct vt_stat __user *vtstat = up; unsigned short state, mask; - /* Review: FIXME: Console lock ? */ if (put_user(fg_console + 1, &vtstat->v_active)) ret = -EFAULT; else { state = 1; /* /dev/tty0 is always open */ + console_lock(); /* required by vt_in_use() */ for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1) - if (VT_IS_IN_USE(i)) + if (vt_in_use(i)) state |= mask; + console_unlock(); ret = put_user(state, &vtstat->v_state); } break; @@ -659,10 +668,11 @@ int vt_ioctl(struct tty_struct *tty, * Returns the first available (non-opened) console. */ case VT_OPENQRY: - /* FIXME: locking ? - but then this is a stupid API */ + console_lock(); /* required by vt_in_use() */ for (i = 0; i < MAX_NR_CONSOLES; ++i) - if (! VT_IS_IN_USE(i)) + if (!vt_in_use(i)) break; + console_unlock(); uival = i < MAX_NR_CONSOLES ? (i+1) : -1; goto setint; @@ -1011,12 +1021,12 @@ int vt_ioctl(struct tty_struct *tty, case VT_LOCKSWITCH: if (!capable(CAP_SYS_TTY_CONFIG)) return -EPERM; - vt_dont_switch = 1; + vt_dont_switch = true; break; case VT_UNLOCKSWITCH: if (!capable(CAP_SYS_TTY_CONFIG)) return -EPERM; - vt_dont_switch = 0; + vt_dont_switch = false; break; case VT_GETHIFONTMASK: ret = put_user(vc->vc_hi_font_mask, @@ -1180,14 +1190,9 @@ long vt_compat_ioctl(struct tty_struct *tty, { struct vc_data *vc = tty->driver_data; struct console_font_op op; /* used in multiple places here */ - unsigned int console = vc->vc_num; void __user *up = compat_ptr(arg); int perm; - - if (!vc_cons_allocated(console)) /* impossible? */ - return -ENOIOCTLCMD; - /* * To have permissions to do most of the vt ioctls, we either have * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index 02f6ca2cb1ba..f624cc87cbab 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -2107,7 +2107,7 @@ found: /* Update ring only if removed request is on pending_req_list list */ if (req_on_hw_ring) { link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma + - (priv_req->start_trb * TRB_SIZE)); + ((priv_req->end_trb + 1) * TRB_SIZE)); link_trb->control = (link_trb->control & TRB_CYCLE) | TRB_TYPE(TRB_LINK) | TRB_CHAIN; @@ -2152,11 +2152,21 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) { struct cdns3_device *priv_dev = priv_ep->cdns3_dev; struct usb_request *request; + struct cdns3_request *priv_req; + struct cdns3_trb *trb = NULL; int ret; int val; trace_cdns3_halt(priv_ep, 0, 0); + request = cdns3_next_request(&priv_ep->pending_req_list); + if (request) { + priv_req = to_cdns3_request(request); + trb = priv_req->trb; + if (trb) + trb->control = trb->control ^ TRB_CYCLE; + } + writel(EP_CMD_CSTALL | EP_CMD_EPRST, &priv_dev->regs->ep_cmd); /* wait for EPRST cleared */ @@ -2167,10 +2177,11 @@ int __cdns3_gadget_ep_clear_halt(struct cdns3_endpoint *priv_ep) priv_ep->flags &= ~(EP_STALLED | EP_STALL_PENDING); - request = cdns3_next_request(&priv_ep->pending_req_list); - - if (request) + if (request) { + if (trb) + trb->control = trb->control ^ TRB_CYCLE; cdns3_rearm_transfer(priv_ep, 1); + } cdns3_start_all_request(priv_dev, priv_ep); return ret; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 62f4fb9b362f..84d6f7df09a4 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -896,10 +896,10 @@ static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss) ss->xmit_fifo_size = acm->writesize; ss->baud_base = le32_to_cpu(acm->line.dwDTERate); - ss->close_delay = acm->port.close_delay / 10; + ss->close_delay = jiffies_to_msecs(acm->port.close_delay) / 10; ss->closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? ASYNC_CLOSING_WAIT_NONE : - acm->port.closing_wait / 10; + jiffies_to_msecs(acm->port.closing_wait) / 10; return 0; } @@ -907,17 +907,25 @@ static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss) { struct acm *acm = tty->driver_data; unsigned int closing_wait, close_delay; + unsigned int old_closing_wait, old_close_delay; int retval = 0; - close_delay = ss->close_delay * 10; + close_delay = msecs_to_jiffies(ss->close_delay * 10); closing_wait = ss->closing_wait == ASYNC_CLOSING_WAIT_NONE ? - ASYNC_CLOSING_WAIT_NONE : ss->closing_wait * 10; + ASYNC_CLOSING_WAIT_NONE : + msecs_to_jiffies(ss->closing_wait * 10); + + /* we must redo the rounding here, so that the values match */ + old_close_delay = jiffies_to_msecs(acm->port.close_delay) / 10; + old_closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + jiffies_to_msecs(acm->port.closing_wait) / 10; mutex_lock(&acm->port.mutex); if (!capable(CAP_SYS_ADMIN)) { - if ((close_delay != acm->port.close_delay) || - (closing_wait != acm->port.closing_wait)) + if ((ss->close_delay != old_close_delay) || + (ss->closing_wait != old_closing_wait)) retval = -EPERM; else retval = -EOPNOTSUPP; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 617c7e9049b3..f88b0d772a8f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -988,13 +988,17 @@ int usb_remove_device(struct usb_device *udev) { struct usb_hub *hub; struct usb_interface *intf; + int ret; if (!udev->parent) /* Can't remove a root hub */ return -EINVAL; hub = usb_hub_to_struct_hub(udev->parent); intf = to_usb_interface(hub->intfdev); - usb_autopm_get_interface(intf); + ret = usb_autopm_get_interface(intf); + if (ret < 0) + return ret; + set_bit(udev->portnum, hub->removed_bits); hub_port_logical_disconnect(hub, udev->portnum); usb_autopm_put_interface(intf); @@ -1866,7 +1870,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) { hub->quirk_disable_autosuspend = 1; - usb_autopm_get_interface(intf); + usb_autopm_get_interface_no_resume(intf); } if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index bbbb35fa639f..235a7c645503 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -213,7 +213,10 @@ static int usb_port_runtime_resume(struct device *dev) if (!port_dev->is_superspeed && peer) pm_runtime_get_sync(&peer->dev); - usb_autopm_get_interface(intf); + retval = usb_autopm_get_interface(intf); + if (retval < 0) + return retval; + retval = usb_hub_set_port_power(hdev, hub, port1, true); msleep(hub_power_on_good_delay(hub)); if (udev && !retval) { @@ -266,7 +269,10 @@ static int usb_port_runtime_suspend(struct device *dev) if (usb_port_block_power_off) return -EBUSY; - usb_autopm_get_interface(intf); + retval = usb_autopm_get_interface(intf); + if (retval < 0) + return retval; + retval = usb_hub_set_port_power(hdev, hub, port1, false); usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); if (!port_dev->is_superspeed) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 2b24336a72e5..da30b5664ff3 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -231,6 +231,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Logitech PTZ Pro Camera */ { USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT }, + /* Logitech Screen Share */ + { USB_DEVICE(0x046d, 0x086c), .driver_info = USB_QUIRK_NO_LPM }, + /* Logitech Quickcam Fusion */ { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -375,6 +378,12 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0b05, 0x17e0), .driver_info = USB_QUIRK_IGNORE_REMOTE_WAKEUP }, + /* Realtek hub in Dell WD19 (Type-C) */ + { USB_DEVICE(0x0bda, 0x0487), .driver_info = USB_QUIRK_NO_LPM }, + + /* Generic RTL8153 based ethernet adapters */ + { USB_DEVICE(0x0bda, 0x8153), .driver_info = USB_QUIRK_NO_LPM }, + /* Action Semiconductor flash disk */ { USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255 }, diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 8a0300b6e3f4..8e7b8c7fb966 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -307,12 +307,6 @@ done: return 0; } -static const struct clk_bulk_data dwc3_core_clks[] = { - { .id = "ref" }, - { .id = "bus_early" }, - { .id = "suspend" }, -}; - /* * dwc3_frame_length_adjustment - Adjusts frame length if required * @dwc3: Pointer to our controller context structure @@ -1524,11 +1518,6 @@ static int dwc3_probe(struct platform_device *pdev) if (!dwc) return -ENOMEM; - dwc->clks = devm_kmemdup(dev, dwc3_core_clks, sizeof(dwc3_core_clks), - GFP_KERNEL); - if (!dwc->clks) - return -ENOMEM; - dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -1582,22 +1571,23 @@ static int dwc3_probe(struct platform_device *pdev) dwc3_get_properties(dwc); - dwc->reset = devm_reset_control_get_optional_shared(dev, NULL); + dwc->reset = devm_reset_control_array_get(dev, true, true); if (IS_ERR(dwc->reset)) return PTR_ERR(dwc->reset); if (dev->of_node) { - dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); - - ret = devm_clk_bulk_get_optional(dev, dwc->num_clks, dwc->clks); + ret = devm_clk_bulk_get_all(dev, &dwc->clks); if (ret == -EPROBE_DEFER) goto err0; /* * Clocks are optional, but new DT platforms should support all * clocks as required by the DT-binding. */ - if (ret) + if (ret < 0) dwc->num_clks = 0; + else + dwc->num_clks = ret; + } ret = reset_control_deassert(dwc->reset); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 17bbeab3576b..a7ac500b13fe 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -1033,6 +1034,9 @@ struct dwc3_scratchpad_array { * @hsphy_mode: UTMI phy mode, one of following: * - USBPHY_INTERFACE_MODE_UTMI * - USBPHY_INTERFACE_MODE_UTMIW + * @role_sw: usb_role_switch handle + * @role_switch_default_mode: default operation mode of controller while + * usb role is USB_ROLE_NONE. * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @usb2_generic_phy: pointer to USB2 PHY @@ -1185,6 +1189,8 @@ struct dwc3 { struct extcon_dev *edev; struct notifier_block edev_nb; enum usb_phy_interface hsphy_mode; + struct usb_role_switch *role_sw; + enum usb_dr_mode role_switch_default_mode; u32 fladj; u32 irq_gadget; diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index c946d64142ad..db68d48c2267 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c @@ -476,6 +476,92 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) return edev; } +#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) +#define ROLE_SWITCH 1 +static int dwc3_usb_role_switch_set(struct device *dev, enum usb_role role) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + u32 mode; + + switch (role) { + case USB_ROLE_HOST: + mode = DWC3_GCTL_PRTCAP_HOST; + break; + case USB_ROLE_DEVICE: + mode = DWC3_GCTL_PRTCAP_DEVICE; + break; + default: + if (dwc->role_switch_default_mode == USB_DR_MODE_HOST) + mode = DWC3_GCTL_PRTCAP_HOST; + else + mode = DWC3_GCTL_PRTCAP_DEVICE; + break; + } + + dwc3_set_mode(dwc, mode); + return 0; +} + +static enum usb_role dwc3_usb_role_switch_get(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + unsigned long flags; + enum usb_role role; + + spin_lock_irqsave(&dwc->lock, flags); + switch (dwc->current_dr_role) { + case DWC3_GCTL_PRTCAP_HOST: + role = USB_ROLE_HOST; + break; + case DWC3_GCTL_PRTCAP_DEVICE: + role = USB_ROLE_DEVICE; + break; + case DWC3_GCTL_PRTCAP_OTG: + role = dwc->current_otg_role; + break; + default: + if (dwc->role_switch_default_mode == USB_DR_MODE_HOST) + role = USB_ROLE_HOST; + else + role = USB_ROLE_DEVICE; + break; + } + spin_unlock_irqrestore(&dwc->lock, flags); + return role; +} + +static int dwc3_setup_role_switch(struct dwc3 *dwc) +{ + struct usb_role_switch_desc dwc3_role_switch = {NULL}; + const char *str; + u32 mode; + int ret; + + ret = device_property_read_string(dwc->dev, "role-switch-default-mode", + &str); + if (ret >= 0 && !strncmp(str, "host", strlen("host"))) { + dwc->role_switch_default_mode = USB_DR_MODE_HOST; + mode = DWC3_GCTL_PRTCAP_HOST; + } else { + dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL; + mode = DWC3_GCTL_PRTCAP_DEVICE; + } + + dwc3_role_switch.fwnode = dev_fwnode(dwc->dev); + dwc3_role_switch.set = dwc3_usb_role_switch_set; + dwc3_role_switch.get = dwc3_usb_role_switch_get; + dwc->role_sw = usb_role_switch_register(dwc->dev, &dwc3_role_switch); + if (IS_ERR(dwc->role_sw)) + return PTR_ERR(dwc->role_sw); + + dwc3_set_mode(dwc, mode); + return 0; +} +#else +#define ROLE_SWITCH 0 +#define dwc3_setup_role_switch(x) 0 +#endif + int dwc3_drd_init(struct dwc3 *dwc) { int ret, irq; @@ -484,7 +570,12 @@ int dwc3_drd_init(struct dwc3 *dwc) if (IS_ERR(dwc->edev)) return PTR_ERR(dwc->edev); - if (dwc->edev) { + if (ROLE_SWITCH && + device_property_read_bool(dwc->dev, "usb-role-switch")) { + ret = dwc3_setup_role_switch(dwc); + if (ret < 0) + return ret; + } else if (dwc->edev) { dwc->edev_nb.notifier_call = dwc3_drd_notifier; ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST, &dwc->edev_nb); @@ -531,6 +622,9 @@ void dwc3_drd_exit(struct dwc3 *dwc) { unsigned long flags; + if (dwc->role_sw) + usb_role_switch_unregister(dwc->role_sw); + if (dwc->edev) extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST, &dwc->edev_nb); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1c9bbdee3c89..491a3aaa1063 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1190,11 +1190,11 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, unsigned chain = true; /* - * IOMMU driver is clubbing the list of sgs which shares a page - * boundary into one and giving it to USB driver. With this the - * number of sgs mapped it not equal to the the number of sgs - * passed. Mark the chain bit to false if it is the last mapped - * sg. + * IOMMU driver is coalescing the list of sgs which shares a + * page boundary into one and giving it to USB driver. With + * this the number of sgs mapped is not equal to the number of + * sgs passed. So mark the chain bit to false if it isthe last + * mapped sg. */ if (i == remaining - 1) chain = false; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 72f323bbd9b8..ec6507314155 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -606,34 +606,6 @@ config USB_FUNC_WAKEUP_SUPPORTED composite driver, which in turn will issue a device notification packet request to the device controller driver. -choice - tristate "USB Gadget precomposed configurations" - default USB_ETH - optional - help - A Linux "Gadget Driver" talks to the USB Peripheral Controller - driver through the abstract "gadget" API. Some other operating - systems call these "client" drivers, of which "class drivers" - are a subset (implementing a USB device class specification). - A gadget driver implements one or more USB functions using - the peripheral hardware. - - Gadget drivers are hardware-neutral, or "platform independent", - except that they sometimes must understand quirks or limitations - of the particular controllers they work with. For example, when - a controller doesn't support alternate configurations or provide - enough of the right types of endpoints, the gadget driver might - not be able work with that controller, or might need to implement - a less common variant of a device class protocol. - - The available choices each represent a single precomposed USB - gadget configuration. In the device model, each option contains - both the device instantiation as a child for a USB gadget - controller, and the relevant drivers for each function declared - by the device. - source "drivers/usb/gadget/legacy/Kconfig" -endchoice - endif # USB_GADGET diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index ead9776d3dac..6c0c6cef4810 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1263,6 +1263,7 @@ static int ffs_aio_cancel(struct kiocb *kiocb) struct ffs_io_data *io_data = kiocb->private; struct ffs_epfile *epfile = kiocb->ki_filp->private_data; struct ffs_data *ffs = epfile->ffs; + unsigned long flags; int value; ENTER(); @@ -1270,14 +1271,14 @@ static int ffs_aio_cancel(struct kiocb *kiocb) ffs_log("enter:state %d setup_state %d flag %lu", epfile->ffs->state, epfile->ffs->setup_state, epfile->ffs->flags); - spin_lock_irq(&epfile->ffs->eps_lock); + spin_lock_irqsave(&epfile->ffs->eps_lock, flags); if (likely(io_data && io_data->ep && io_data->req)) value = usb_ep_dequeue(io_data->ep, io_data->req); else value = -EINVAL; - spin_unlock_irq(&epfile->ffs->eps_lock); + spin_unlock_irqrestore(&epfile->ffs->eps_lock, flags); ffs_log("exit: value %d", value); diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c index bb1e2e1d0076..038c445a4e9b 100644 --- a/drivers/usb/gadget/function/u_serial.c +++ b/drivers/usb/gadget/function/u_serial.c @@ -560,8 +560,10 @@ static int gs_start_io(struct gs_port *port) port->n_read = 0; started = gs_start_rx(port); - /* unblock any pending writes into our circular buffer */ if (started) { + gs_start_tx(port); + /* Unblock any pending writes into our circular buffer, in case + * we didn't in gs_start_tx() */ tty_wakeup(port->port.tty); } else { gs_free_requests(ep, head, &port->read_allocated); diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index 69ff7f8c86f5..abf7a059427f 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -14,6 +14,32 @@ # both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG). # +choice + tristate "USB Gadget precomposed configurations" + default USB_ETH + optional + help + A Linux "Gadget Driver" talks to the USB Peripheral Controller + driver through the abstract "gadget" API. Some other operating + systems call these "client" drivers, of which "class drivers" + are a subset (implementing a USB device class specification). + A gadget driver implements one or more USB functions using + the peripheral hardware. + + Gadget drivers are hardware-neutral, or "platform independent", + except that they sometimes must understand quirks or limitations + of the particular controllers they work with. For example, when + a controller doesn't support alternate configurations or provide + enough of the right types of endpoints, the gadget driver might + not be able work with that controller, or might need to implement + a less common variant of a device class protocol. + + The available choices each represent a single precomposed USB + gadget configuration. In the device model, each option contains + both the device instantiation as a child for a USB gadget + controller, and the relevant drivers for each function declared + by the device. + config USB_ZERO tristate "Gadget Zero (DEVELOPMENT)" select USB_LIBCOMPOSITE @@ -489,3 +515,16 @@ config USB_G_WEBCAM Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_webcam". + +config USB_RAW_GADGET + tristate "USB Raw Gadget" + help + USB Raw Gadget is a kernel module that provides a userspace interface + for the USB Gadget subsystem. Essentially it allows to emulate USB + devices from userspace. See Documentation/usb/raw-gadget.rst for + details. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "raw_gadget". + +endchoice diff --git a/drivers/usb/gadget/legacy/Makefile b/drivers/usb/gadget/legacy/Makefile index abd0c3e66a05..4d864bf82799 100644 --- a/drivers/usb/gadget/legacy/Makefile +++ b/drivers/usb/gadget/legacy/Makefile @@ -43,3 +43,4 @@ obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o obj-$(CONFIG_USB_G_NCM) += g_ncm.o obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o +obj-$(CONFIG_USB_RAW_GADGET) += raw_gadget.o diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c new file mode 100644 index 000000000000..76406343fbe5 --- /dev/null +++ b/drivers/usb/gadget/legacy/raw_gadget.c @@ -0,0 +1,1078 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * USB Raw Gadget driver. + * See Documentation/usb/raw-gadget.rst for more details. + * + * Andrey Konovalov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define DRIVER_DESC "USB Raw Gadget" +#define DRIVER_NAME "raw-gadget" + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Andrey Konovalov"); +MODULE_LICENSE("GPL"); + +/*----------------------------------------------------------------------*/ + +#define RAW_EVENT_QUEUE_SIZE 16 + +struct raw_event_queue { + /* See the comment in raw_event_queue_fetch() for locking details. */ + spinlock_t lock; + struct semaphore sema; + struct usb_raw_event *events[RAW_EVENT_QUEUE_SIZE]; + int size; +}; + +static void raw_event_queue_init(struct raw_event_queue *queue) +{ + spin_lock_init(&queue->lock); + sema_init(&queue->sema, 0); + queue->size = 0; +} + +static int raw_event_queue_add(struct raw_event_queue *queue, + enum usb_raw_event_type type, size_t length, const void *data) +{ + unsigned long flags; + struct usb_raw_event *event; + + spin_lock_irqsave(&queue->lock, flags); + if (WARN_ON(queue->size >= RAW_EVENT_QUEUE_SIZE)) { + spin_unlock_irqrestore(&queue->lock, flags); + return -ENOMEM; + } + event = kmalloc(sizeof(*event) + length, GFP_ATOMIC); + if (!event) { + spin_unlock_irqrestore(&queue->lock, flags); + return -ENOMEM; + } + event->type = type; + event->length = length; + if (event->length) + memcpy(&event->data[0], data, length); + queue->events[queue->size] = event; + queue->size++; + up(&queue->sema); + spin_unlock_irqrestore(&queue->lock, flags); + return 0; +} + +static struct usb_raw_event *raw_event_queue_fetch( + struct raw_event_queue *queue) +{ + unsigned long flags; + struct usb_raw_event *event; + + /* + * This function can be called concurrently. We first check that + * there's at least one event queued by decrementing the semaphore, + * and then take the lock to protect queue struct fields. + */ + if (down_interruptible(&queue->sema)) + return NULL; + spin_lock_irqsave(&queue->lock, flags); + if (WARN_ON(!queue->size)) + return NULL; + event = queue->events[0]; + queue->size--; + memmove(&queue->events[0], &queue->events[1], + queue->size * sizeof(queue->events[0])); + spin_unlock_irqrestore(&queue->lock, flags); + return event; +} + +static void raw_event_queue_destroy(struct raw_event_queue *queue) +{ + int i; + + for (i = 0; i < queue->size; i++) + kfree(queue->events[i]); + queue->size = 0; +} + +/*----------------------------------------------------------------------*/ + +struct raw_dev; + +#define USB_RAW_MAX_ENDPOINTS 32 + +enum ep_state { + STATE_EP_DISABLED, + STATE_EP_ENABLED, +}; + +struct raw_ep { + struct raw_dev *dev; + enum ep_state state; + struct usb_ep *ep; + struct usb_request *req; + bool urb_queued; + bool disabling; + ssize_t status; +}; + +enum dev_state { + STATE_DEV_INVALID = 0, + STATE_DEV_OPENED, + STATE_DEV_INITIALIZED, + STATE_DEV_RUNNING, + STATE_DEV_CLOSED, + STATE_DEV_FAILED +}; + +struct raw_dev { + struct kref count; + spinlock_t lock; + + const char *udc_name; + struct usb_gadget_driver driver; + + /* Reference to misc device: */ + struct device *dev; + + /* Protected by lock: */ + enum dev_state state; + bool gadget_registered; + struct usb_gadget *gadget; + struct usb_request *req; + bool ep0_in_pending; + bool ep0_out_pending; + bool ep0_urb_queued; + ssize_t ep0_status; + struct raw_ep eps[USB_RAW_MAX_ENDPOINTS]; + + struct completion ep0_done; + struct raw_event_queue queue; +}; + +static struct raw_dev *dev_new(void) +{ + struct raw_dev *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + /* Matches kref_put() in raw_release(). */ + kref_init(&dev->count); + spin_lock_init(&dev->lock); + init_completion(&dev->ep0_done); + raw_event_queue_init(&dev->queue); + return dev; +} + +static void dev_free(struct kref *kref) +{ + struct raw_dev *dev = container_of(kref, struct raw_dev, count); + int i; + + kfree(dev->udc_name); + kfree(dev->driver.udc_name); + if (dev->req) { + if (dev->ep0_urb_queued) + usb_ep_dequeue(dev->gadget->ep0, dev->req); + usb_ep_free_request(dev->gadget->ep0, dev->req); + } + raw_event_queue_destroy(&dev->queue); + for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) { + if (dev->eps[i].state != STATE_EP_ENABLED) + continue; + usb_ep_disable(dev->eps[i].ep); + usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); + kfree(dev->eps[i].ep->desc); + dev->eps[i].state = STATE_EP_DISABLED; + } + kfree(dev); +} + +/*----------------------------------------------------------------------*/ + +static int raw_queue_event(struct raw_dev *dev, + enum usb_raw_event_type type, size_t length, const void *data) +{ + int ret = 0; + unsigned long flags; + + ret = raw_event_queue_add(&dev->queue, type, length, data); + if (ret < 0) { + spin_lock_irqsave(&dev->lock, flags); + dev->state = STATE_DEV_FAILED; + spin_unlock_irqrestore(&dev->lock, flags); + } + return ret; +} + +static void gadget_ep0_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct raw_dev *dev = req->context; + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (req->status) + dev->ep0_status = req->status; + else + dev->ep0_status = req->actual; + if (dev->ep0_in_pending) + dev->ep0_in_pending = false; + else + dev->ep0_out_pending = false; + spin_unlock_irqrestore(&dev->lock, flags); + + complete(&dev->ep0_done); +} + +static int gadget_bind(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) +{ + int ret = 0; + struct raw_dev *dev = container_of(driver, struct raw_dev, driver); + struct usb_request *req; + unsigned long flags; + + if (strcmp(gadget->name, dev->udc_name) != 0) + return -ENODEV; + + set_gadget_data(gadget, dev); + req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); + if (!req) { + dev_err(&gadget->dev, "usb_ep_alloc_request failed\n"); + set_gadget_data(gadget, NULL); + return -ENOMEM; + } + + spin_lock_irqsave(&dev->lock, flags); + dev->req = req; + dev->req->context = dev; + dev->req->complete = gadget_ep0_complete; + dev->gadget = gadget; + spin_unlock_irqrestore(&dev->lock, flags); + + /* Matches kref_put() in gadget_unbind(). */ + kref_get(&dev->count); + + ret = raw_queue_event(dev, USB_RAW_EVENT_CONNECT, 0, NULL); + if (ret < 0) + dev_err(&gadget->dev, "failed to queue event\n"); + + return ret; +} + +static void gadget_unbind(struct usb_gadget *gadget) +{ + struct raw_dev *dev = get_gadget_data(gadget); + + set_gadget_data(gadget, NULL); + /* Matches kref_get() in gadget_bind(). */ + kref_put(&dev->count, dev_free); +} + +static int gadget_setup(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl) +{ + int ret = 0; + struct raw_dev *dev = get_gadget_data(gadget); + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_err(&gadget->dev, "ignoring, device is not running\n"); + ret = -ENODEV; + goto out_unlock; + } + if (dev->ep0_in_pending || dev->ep0_out_pending) { + dev_dbg(&gadget->dev, "stalling, request already pending\n"); + ret = -EBUSY; + goto out_unlock; + } + if ((ctrl->bRequestType & USB_DIR_IN) && ctrl->wLength) + dev->ep0_in_pending = true; + else + dev->ep0_out_pending = true; + spin_unlock_irqrestore(&dev->lock, flags); + + ret = raw_queue_event(dev, USB_RAW_EVENT_CONTROL, sizeof(*ctrl), ctrl); + if (ret < 0) + dev_err(&gadget->dev, "failed to queue event\n"); + goto out; + +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); +out: + return ret; +} + +/* These are currently unused but present in case UDC driver requires them. */ +static void gadget_disconnect(struct usb_gadget *gadget) { } +static void gadget_suspend(struct usb_gadget *gadget) { } +static void gadget_resume(struct usb_gadget *gadget) { } +static void gadget_reset(struct usb_gadget *gadget) { } + +/*----------------------------------------------------------------------*/ + +static struct miscdevice raw_misc_device; + +static int raw_open(struct inode *inode, struct file *fd) +{ + struct raw_dev *dev; + + /* Nonblocking I/O is not supported yet. */ + if (fd->f_flags & O_NONBLOCK) + return -EINVAL; + + dev = dev_new(); + if (!dev) + return -ENOMEM; + fd->private_data = dev; + dev->state = STATE_DEV_OPENED; + dev->dev = raw_misc_device.this_device; + return 0; +} + +static int raw_release(struct inode *inode, struct file *fd) +{ + int ret = 0; + struct raw_dev *dev = fd->private_data; + unsigned long flags; + bool unregister = false; + + spin_lock_irqsave(&dev->lock, flags); + dev->state = STATE_DEV_CLOSED; + if (!dev->gadget) { + spin_unlock_irqrestore(&dev->lock, flags); + goto out_put; + } + if (dev->gadget_registered) + unregister = true; + dev->gadget_registered = false; + spin_unlock_irqrestore(&dev->lock, flags); + + if (unregister) { + ret = usb_gadget_unregister_driver(&dev->driver); + if (ret != 0) + dev_err(dev->dev, + "usb_gadget_unregister_driver() failed with %d\n", + ret); + /* Matches kref_get() in raw_ioctl_run(). */ + kref_put(&dev->count, dev_free); + } + +out_put: + /* Matches dev_new() in raw_open(). */ + kref_put(&dev->count, dev_free); + return ret; +} + +/*----------------------------------------------------------------------*/ + +static int raw_ioctl_init(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + struct usb_raw_init arg; + char *udc_driver_name; + char *udc_device_name; + unsigned long flags; + + ret = copy_from_user(&arg, (void __user *)value, sizeof(arg)); + if (ret) + return ret; + + switch (arg.speed) { + case USB_SPEED_UNKNOWN: + arg.speed = USB_SPEED_HIGH; + break; + case USB_SPEED_LOW: + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + case USB_SPEED_SUPER: + break; + default: + return -EINVAL; + } + + udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); + if (!udc_driver_name) + return -ENOMEM; + ret = strscpy(udc_driver_name, &arg.driver_name[0], + UDC_NAME_LENGTH_MAX); + if (ret < 0) { + kfree(udc_driver_name); + return ret; + } + ret = 0; + + udc_device_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); + if (!udc_device_name) { + kfree(udc_driver_name); + return -ENOMEM; + } + ret = strscpy(udc_device_name, &arg.device_name[0], + UDC_NAME_LENGTH_MAX); + if (ret < 0) { + kfree(udc_driver_name); + kfree(udc_device_name); + return ret; + } + ret = 0; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_OPENED) { + dev_dbg(dev->dev, "fail, device is not opened\n"); + kfree(udc_driver_name); + kfree(udc_device_name); + ret = -EINVAL; + goto out_unlock; + } + dev->udc_name = udc_driver_name; + + dev->driver.function = DRIVER_DESC; + dev->driver.max_speed = arg.speed; + dev->driver.setup = gadget_setup; + dev->driver.disconnect = gadget_disconnect; + dev->driver.bind = gadget_bind; + dev->driver.unbind = gadget_unbind; + dev->driver.suspend = gadget_suspend; + dev->driver.resume = gadget_resume; + dev->driver.reset = gadget_reset; + dev->driver.driver.name = DRIVER_NAME; + dev->driver.udc_name = udc_device_name; + dev->driver.match_existing_only = 1; + + dev->state = STATE_DEV_INITIALIZED; + +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + +static int raw_ioctl_run(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + unsigned long flags; + + if (value) + return -EINVAL; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_INITIALIZED) { + dev_dbg(dev->dev, "fail, device is not initialized\n"); + ret = -EINVAL; + goto out_unlock; + } + spin_unlock_irqrestore(&dev->lock, flags); + + ret = usb_gadget_probe_driver(&dev->driver); + + spin_lock_irqsave(&dev->lock, flags); + if (ret) { + dev_err(dev->dev, + "fail, usb_gadget_probe_driver returned %d\n", ret); + dev->state = STATE_DEV_FAILED; + goto out_unlock; + } + dev->gadget_registered = true; + dev->state = STATE_DEV_RUNNING; + /* Matches kref_put() in raw_release(). */ + kref_get(&dev->count); + +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + +static int raw_ioctl_event_fetch(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + struct usb_raw_event arg; + unsigned long flags; + struct usb_raw_event *event; + uint32_t length; + + ret = copy_from_user(&arg, (void __user *)value, sizeof(arg)); + if (ret) + return ret; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + spin_unlock_irqrestore(&dev->lock, flags); + return -EINVAL; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + spin_unlock_irqrestore(&dev->lock, flags); + return -EBUSY; + } + spin_unlock_irqrestore(&dev->lock, flags); + + event = raw_event_queue_fetch(&dev->queue); + if (!event) { + dev_dbg(&dev->gadget->dev, "event fetching interrupted\n"); + return -EINTR; + } + length = min(arg.length, event->length); + ret = copy_to_user((void __user *)value, event, + sizeof(*event) + length); + return ret; +} + +static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr, + bool get_from_user) +{ + int ret; + void *data; + + ret = copy_from_user(io, ptr, sizeof(*io)); + if (ret) + return ERR_PTR(ret); + if (io->ep >= USB_RAW_MAX_ENDPOINTS) + return ERR_PTR(-EINVAL); + if (!usb_raw_io_flags_valid(io->flags)) + return ERR_PTR(-EINVAL); + if (io->length > PAGE_SIZE) + return ERR_PTR(-EINVAL); + if (get_from_user) + data = memdup_user(ptr + sizeof(*io), io->length); + else { + data = kmalloc(io->length, GFP_KERNEL); + if (!data) + data = ERR_PTR(-ENOMEM); + } + return data; +} + +static int raw_process_ep0_io(struct raw_dev *dev, struct usb_raw_ep_io *io, + void *data, bool in) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + goto out_unlock; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + goto out_unlock; + } + if (dev->ep0_urb_queued) { + dev_dbg(&dev->gadget->dev, "fail, urb already queued\n"); + ret = -EBUSY; + goto out_unlock; + } + if ((in && !dev->ep0_in_pending) || + (!in && !dev->ep0_out_pending)) { + dev_dbg(&dev->gadget->dev, "fail, wrong direction\n"); + ret = -EBUSY; + goto out_unlock; + } + if (WARN_ON(in && dev->ep0_out_pending)) { + ret = -ENODEV; + dev->state = STATE_DEV_FAILED; + goto out_done; + } + if (WARN_ON(!in && dev->ep0_in_pending)) { + ret = -ENODEV; + dev->state = STATE_DEV_FAILED; + goto out_done; + } + + dev->req->buf = data; + dev->req->length = io->length; + dev->req->zero = usb_raw_io_flags_zero(io->flags); + dev->ep0_urb_queued = true; + spin_unlock_irqrestore(&dev->lock, flags); + + ret = usb_ep_queue(dev->gadget->ep0, dev->req, GFP_KERNEL); + if (ret) { + dev_err(&dev->gadget->dev, + "fail, usb_ep_queue returned %d\n", ret); + spin_lock_irqsave(&dev->lock, flags); + dev->state = STATE_DEV_FAILED; + goto out_done; + } + + ret = wait_for_completion_interruptible(&dev->ep0_done); + if (ret) { + dev_dbg(&dev->gadget->dev, "wait interrupted\n"); + usb_ep_dequeue(dev->gadget->ep0, dev->req); + wait_for_completion(&dev->ep0_done); + spin_lock_irqsave(&dev->lock, flags); + goto out_done; + } + + spin_lock_irqsave(&dev->lock, flags); + ret = dev->ep0_status; + +out_done: + dev->ep0_urb_queued = false; +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + +static int raw_ioctl_ep0_write(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + void *data; + struct usb_raw_ep_io io; + + data = raw_alloc_io_data(&io, (void __user *)value, true); + if (IS_ERR(data)) + return PTR_ERR(data); + ret = raw_process_ep0_io(dev, &io, data, true); + kfree(data); + return ret; +} + +static int raw_ioctl_ep0_read(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + void *data; + struct usb_raw_ep_io io; + unsigned int length; + + data = raw_alloc_io_data(&io, (void __user *)value, false); + if (IS_ERR(data)) + return PTR_ERR(data); + ret = raw_process_ep0_io(dev, &io, data, false); + if (ret < 0) { + kfree(data); + return ret; + } + length = min(io.length, (unsigned int)ret); + ret = copy_to_user((void __user *)(value + sizeof(io)), data, length); + kfree(data); + return ret; +} + +static bool check_ep_caps(struct usb_ep *ep, + struct usb_endpoint_descriptor *desc) +{ + switch (usb_endpoint_type(desc)) { + case USB_ENDPOINT_XFER_ISOC: + if (!ep->caps.type_iso) + return false; + break; + case USB_ENDPOINT_XFER_BULK: + if (!ep->caps.type_bulk) + return false; + break; + case USB_ENDPOINT_XFER_INT: + if (!ep->caps.type_int) + return false; + break; + default: + return false; + } + + if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) + return false; + if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) + return false; + + return true; +} + +static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) +{ + int ret = 0, i; + unsigned long flags; + struct usb_endpoint_descriptor *desc; + struct usb_ep *ep = NULL; + + desc = memdup_user((void __user *)value, sizeof(*desc)); + if (IS_ERR(desc)) + return PTR_ERR(desc); + + /* + * Endpoints with a maxpacket length of 0 can cause crashes in UDC + * drivers. + */ + if (usb_endpoint_maxp(desc) == 0) { + dev_dbg(dev->dev, "fail, bad endpoint maxpacket\n"); + kfree(desc); + return -EINVAL; + } + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + goto out_free; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + goto out_free; + } + + for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) { + if (dev->eps[i].state == STATE_EP_ENABLED) + continue; + break; + } + if (i == USB_RAW_MAX_ENDPOINTS) { + dev_dbg(&dev->gadget->dev, + "fail, no device endpoints available\n"); + ret = -EBUSY; + goto out_free; + } + + gadget_for_each_ep(ep, dev->gadget) { + if (ep->enabled) + continue; + if (!check_ep_caps(ep, desc)) + continue; + ep->desc = desc; + ret = usb_ep_enable(ep); + if (ret < 0) { + dev_err(&dev->gadget->dev, + "fail, usb_ep_enable returned %d\n", ret); + goto out_free; + } + dev->eps[i].req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (!dev->eps[i].req) { + dev_err(&dev->gadget->dev, + "fail, usb_ep_alloc_request failed\n"); + usb_ep_disable(ep); + ret = -ENOMEM; + goto out_free; + } + dev->eps[i].ep = ep; + dev->eps[i].state = STATE_EP_ENABLED; + ep->driver_data = &dev->eps[i]; + ret = i; + goto out_unlock; + } + + dev_dbg(&dev->gadget->dev, "fail, no gadget endpoints available\n"); + ret = -EBUSY; + +out_free: + kfree(desc); +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + +static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) +{ + int ret = 0, i = value; + unsigned long flags; + const void *desc; + + if (i < 0 || i >= USB_RAW_MAX_ENDPOINTS) + return -EINVAL; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + goto out_unlock; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + goto out_unlock; + } + if (dev->eps[i].state != STATE_EP_ENABLED) { + dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); + ret = -EINVAL; + goto out_unlock; + } + if (dev->eps[i].disabling) { + dev_dbg(&dev->gadget->dev, + "fail, disable already in progress\n"); + ret = -EINVAL; + goto out_unlock; + } + if (dev->eps[i].urb_queued) { + dev_dbg(&dev->gadget->dev, + "fail, waiting for urb completion\n"); + ret = -EINVAL; + goto out_unlock; + } + dev->eps[i].disabling = true; + spin_unlock_irqrestore(&dev->lock, flags); + + usb_ep_disable(dev->eps[i].ep); + + spin_lock_irqsave(&dev->lock, flags); + usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); + desc = dev->eps[i].ep->desc; + dev->eps[i].ep = NULL; + dev->eps[i].state = STATE_EP_DISABLED; + kfree(desc); + dev->eps[i].disabling = false; + +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + +static void gadget_ep_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct raw_ep *r_ep = (struct raw_ep *)ep->driver_data; + struct raw_dev *dev = r_ep->dev; + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (req->status) + r_ep->status = req->status; + else + r_ep->status = req->actual; + spin_unlock_irqrestore(&dev->lock, flags); + + complete((struct completion *)req->context); +} + +static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io, + void *data, bool in) +{ + int ret = 0; + unsigned long flags; + struct raw_ep *ep = &dev->eps[io->ep]; + DECLARE_COMPLETION_ONSTACK(done); + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + goto out_unlock; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + goto out_unlock; + } + if (ep->state != STATE_EP_ENABLED) { + dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); + ret = -EBUSY; + goto out_unlock; + } + if (ep->disabling) { + dev_dbg(&dev->gadget->dev, + "fail, endpoint is already being disabled\n"); + ret = -EBUSY; + goto out_unlock; + } + if (ep->urb_queued) { + dev_dbg(&dev->gadget->dev, "fail, urb already queued\n"); + ret = -EBUSY; + goto out_unlock; + } + if ((in && !ep->ep->caps.dir_in) || (!in && ep->ep->caps.dir_in)) { + dev_dbg(&dev->gadget->dev, "fail, wrong direction\n"); + ret = -EINVAL; + goto out_unlock; + } + + ep->dev = dev; + ep->req->context = &done; + ep->req->complete = gadget_ep_complete; + ep->req->buf = data; + ep->req->length = io->length; + ep->req->zero = usb_raw_io_flags_zero(io->flags); + ep->urb_queued = true; + spin_unlock_irqrestore(&dev->lock, flags); + + ret = usb_ep_queue(ep->ep, ep->req, GFP_KERNEL); + if (ret) { + dev_err(&dev->gadget->dev, + "fail, usb_ep_queue returned %d\n", ret); + spin_lock_irqsave(&dev->lock, flags); + dev->state = STATE_DEV_FAILED; + goto out_done; + } + + ret = wait_for_completion_interruptible(&done); + if (ret) { + dev_dbg(&dev->gadget->dev, "wait interrupted\n"); + usb_ep_dequeue(ep->ep, ep->req); + wait_for_completion(&done); + spin_lock_irqsave(&dev->lock, flags); + goto out_done; + } + + spin_lock_irqsave(&dev->lock, flags); + ret = ep->status; + +out_done: + ep->urb_queued = false; +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + +static int raw_ioctl_ep_write(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + char *data; + struct usb_raw_ep_io io; + + data = raw_alloc_io_data(&io, (void __user *)value, true); + if (IS_ERR(data)) + return PTR_ERR(data); + ret = raw_process_ep_io(dev, &io, data, true); + kfree(data); + return ret; +} + +static int raw_ioctl_ep_read(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + char *data; + struct usb_raw_ep_io io; + unsigned int length; + + data = raw_alloc_io_data(&io, (void __user *)value, false); + if (IS_ERR(data)) + return PTR_ERR(data); + ret = raw_process_ep_io(dev, &io, data, false); + if (ret < 0) { + kfree(data); + return ret; + } + length = min(io.length, (unsigned int)ret); + ret = copy_to_user((void __user *)(value + sizeof(io)), data, length); + kfree(data); + return ret; +} + +static int raw_ioctl_configure(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + unsigned long flags; + + if (value) + return -EINVAL; + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + goto out_unlock; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + goto out_unlock; + } + usb_gadget_set_state(dev->gadget, USB_STATE_CONFIGURED); + +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + +static int raw_ioctl_vbus_draw(struct raw_dev *dev, unsigned long value) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_RUNNING) { + dev_dbg(dev->dev, "fail, device is not running\n"); + ret = -EINVAL; + goto out_unlock; + } + if (!dev->gadget) { + dev_dbg(dev->dev, "fail, gadget is not bound\n"); + ret = -EBUSY; + goto out_unlock; + } + usb_gadget_vbus_draw(dev->gadget, 2 * value); + +out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); + return ret; +} + +static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) +{ + struct raw_dev *dev = fd->private_data; + int ret = 0; + + if (!dev) + return -EBUSY; + + switch (cmd) { + case USB_RAW_IOCTL_INIT: + ret = raw_ioctl_init(dev, value); + break; + case USB_RAW_IOCTL_RUN: + ret = raw_ioctl_run(dev, value); + break; + case USB_RAW_IOCTL_EVENT_FETCH: + ret = raw_ioctl_event_fetch(dev, value); + break; + case USB_RAW_IOCTL_EP0_WRITE: + ret = raw_ioctl_ep0_write(dev, value); + break; + case USB_RAW_IOCTL_EP0_READ: + ret = raw_ioctl_ep0_read(dev, value); + break; + case USB_RAW_IOCTL_EP_ENABLE: + ret = raw_ioctl_ep_enable(dev, value); + break; + case USB_RAW_IOCTL_EP_DISABLE: + ret = raw_ioctl_ep_disable(dev, value); + break; + case USB_RAW_IOCTL_EP_WRITE: + ret = raw_ioctl_ep_write(dev, value); + break; + case USB_RAW_IOCTL_EP_READ: + ret = raw_ioctl_ep_read(dev, value); + break; + case USB_RAW_IOCTL_CONFIGURE: + ret = raw_ioctl_configure(dev, value); + break; + case USB_RAW_IOCTL_VBUS_DRAW: + ret = raw_ioctl_vbus_draw(dev, value); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +/*----------------------------------------------------------------------*/ + +static const struct file_operations raw_fops = { + .open = raw_open, + .unlocked_ioctl = raw_ioctl, + .compat_ioctl = raw_ioctl, + .release = raw_release, + .llseek = no_llseek, +}; + +static struct miscdevice raw_misc_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = DRIVER_NAME, + .fops = &raw_fops, +}; + +module_misc_device(raw_misc_device); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 09c3619b0c10..1bf5f6d82328 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -135,7 +135,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_AMD_PLL_FIX; if (pdev->vendor == PCI_VENDOR_ID_AMD && - (pdev->device == 0x15e0 || + (pdev->device == 0x145c || + pdev->device == 0x15e0 || pdev->device == 0x15e1 || pdev->device == 0x43bb)) xhci->quirks |= XHCI_SUSPEND_DELAY; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 30d0789ed555..ef3845c7888d 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -458,6 +458,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match); static struct platform_driver usb_xhci_driver = { .probe = xhci_plat_probe, .remove = xhci_plat_remove, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "xhci-hcd", .pm = &xhci_plat_pm_ops, diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 052a269d86f2..87da9098fb34 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -289,23 +289,12 @@ DECLARE_EVENT_CLASS(xhci_log_urb, ), TP_printk("ep%d%s-%s: urb %p pipe %u slot %d length %d/%d sgs %d/%d stream %d flags %08x", __entry->epnum, __entry->dir_in ? "in" : "out", - ({ char *s; - switch (__entry->type) { - case USB_ENDPOINT_XFER_INT: - s = "intr"; - break; - case USB_ENDPOINT_XFER_CONTROL: - s = "control"; - break; - case USB_ENDPOINT_XFER_BULK: - s = "bulk"; - break; - case USB_ENDPOINT_XFER_ISOC: - s = "isoc"; - break; - default: - s = "UNKNOWN"; - } s; }), __entry->urb, __entry->pipe, __entry->slot_id, + __print_symbolic(__entry->type, + { USB_ENDPOINT_XFER_INT, "intr" }, + { USB_ENDPOINT_XFER_CONTROL, "control" }, + { USB_ENDPOINT_XFER_BULK, "bulk" }, + { USB_ENDPOINT_XFER_ISOC, "isoc" }), + __entry->urb, __entry->pipe, __entry->slot_id, __entry->actual, __entry->length, __entry->num_mapped_sgs, __entry->num_sgs, __entry->stream, __entry->flags ) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 5a44b70372d9..fa9922c0c910 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1462,10 +1462,7 @@ done: * We need to map sg if the transfer_buffer is * NULL. */ - if (!urb->transfer_buffer) - qh->use_sg = true; - - if (qh->use_sg) { + if (!urb->transfer_buffer) { /* sg_miter_start is already done in musb_ep_program */ if (!sg_miter_next(&qh->sg_miter)) { dev_err(musb->controller, "error: sg list empty\n"); @@ -1473,9 +1470,8 @@ done: status = -EINVAL; goto done; } - urb->transfer_buffer = qh->sg_miter.addr; length = min_t(u32, length, qh->sg_miter.length); - musb_write_fifo(hw_ep, length, urb->transfer_buffer); + musb_write_fifo(hw_ep, length, qh->sg_miter.addr); qh->sg_miter.consumed = length; sg_miter_stop(&qh->sg_miter); } else { @@ -1484,11 +1480,6 @@ done: qh->segsize = length; - if (qh->use_sg) { - if (offset + length >= urb->transfer_buffer_length) - qh->use_sg = false; - } - musb_ep_select(mbase, epnum); musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); @@ -2003,8 +1994,10 @@ finish: urb->actual_length += xfer_len; qh->offset += xfer_len; if (done) { - if (qh->use_sg) + if (qh->use_sg) { qh->use_sg = false; + urb->transfer_buffer = NULL; + } if (urb->status == -EINPROGRESS) urb->status = status; diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 5737add6a2a4..4cca0b836f43 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -710,7 +710,7 @@ static void edge_interrupt_callback(struct urb *urb) /* grab the txcredits for the ports if available */ position = 2; portNumber = 0; - while ((position < length) && + while ((position < length - 1) && (portNumber < edge_serial->serial->num_ports)) { txCredits = data[position] | (data[position+1] << 8); if (txCredits) { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 084cc2fff3ae..8bfffca3e4ae 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1183,6 +1183,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x110a, 0xff), /* Telit ME910G1 */ .driver_info = NCTRL(0) | RSVD(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x110b, 0xff), /* Telit ME910G1 (ECM) */ + .driver_info = NCTRL(0) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4), @@ -1990,8 +1992,14 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x7e11, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/A3 */ + { USB_DEVICE_INTERFACE_CLASS(0x1435, 0xd191, 0xff), /* Wistron Neweb D19Q1 */ + .driver_info = RSVD(1) | RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(0x1690, 0x7588, 0xff), /* ASKEY WWHC050 */ + .driver_info = RSVD(1) | RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2031, 0xff), /* Olicard 600 */ .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2033, 0xff), /* BroadMobi BM806U */ + .driver_info = RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x2060, 0xff), /* BroadMobi BM818 */ .driver_info = RSVD(4) }, { USB_DEVICE_INTERFACE_CLASS(0x2020, 0x4000, 0xff) }, /* OLICARD300 - MT6225 */ diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 9d27b76c5c6e..e6d9b79d3521 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -93,6 +93,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD220TA_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD381_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD960TA_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index b0175f17d1a2..c98db6b650a5 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -124,6 +124,7 @@ #define HP_LM920_PRODUCT_ID 0x026b #define HP_TD620_PRODUCT_ID 0x0956 #define HP_LD960_PRODUCT_ID 0x0b39 +#define HP_LD381_PRODUCT_ID 0x0f7f #define HP_LCM220_PRODUCT_ID 0x3139 #define HP_LCM960_PRODUCT_ID 0x3239 #define HP_LD220_PRODUCT_ID 0x3524 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1cd9b6305b06..1880f3e13f57 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1258,6 +1258,12 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, USB_SC_RBC, USB_PR_BULK, NULL, 0 ), +UNUSUAL_DEV(0x090c, 0x1000, 0x1100, 0x1100, + "Samsung", + "Flash Drive FIT", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64), + /* aeb */ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, "Feiya", diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c index d4d5189edfb8..77655d9ce549 100644 --- a/drivers/usb/typec/ucsi/displayport.c +++ b/drivers/usb/typec/ucsi/displayport.c @@ -271,6 +271,9 @@ void ucsi_displayport_remove_partner(struct typec_altmode *alt) return; dp = typec_altmode_get_drvdata(alt); + if (!dp) + return; + dp->data.conf = 0; dp->data.status = 0; dp->initialized = false; @@ -285,6 +288,8 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con, struct typec_altmode *alt; struct ucsi_dp *dp; + mutex_lock(&con->lock); + /* We can't rely on the firmware with the capabilities. */ desc->vdo |= DP_CAP_DP_SIGNALING | DP_CAP_RECEPTACLE; @@ -293,12 +298,15 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con, desc->vdo |= all_assignments << 16; alt = typec_port_register_altmode(con->port, desc); - if (IS_ERR(alt)) + if (IS_ERR(alt)) { + mutex_unlock(&con->lock); return alt; + } dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL); if (!dp) { typec_unregister_altmode(alt); + mutex_unlock(&con->lock); return ERR_PTR(-ENOMEM); } @@ -311,5 +319,7 @@ struct typec_altmode *ucsi_register_displayport(struct ucsi_connector *con, alt->ops = &ucsi_displayport_ops; typec_altmode_set_drvdata(alt, dp); + mutex_unlock(&con->lock); + return alt; } diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index c6b3bdbbdbc9..bfaa9ec4bc1f 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1316,6 +1316,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) static int vgacon_resize(struct vc_data *c, unsigned int width, unsigned int height, unsigned int user) { + if ((width << 1) * height > vga_vram_size) + return -EINVAL; + if (width % 2 || width > screen_info.orig_video_cols || height > (screen_info.orig_video_lines * vga_default_font_height)/ c->vc_font.height) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index d2c4eb9efd70..7aaf150f89ba 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -958,8 +958,8 @@ out_iput: iput(vb->vb_dev_info.inode); out_kern_unmount: kern_unmount(balloon_mnt); -#endif out_del_vqs: +#endif vdev->config->del_vqs(vdev); out_free_vb: kfree(vb); diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 867c7ebd3f10..58b96baa8d48 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -2203,10 +2203,10 @@ void vring_del_virtqueue(struct virtqueue *_vq) vq->split.queue_size_in_bytes, vq->split.vring.desc, vq->split.queue_dma_addr); - - kfree(vq->split.desc_state); } } + if (!vq->packed_ring) + kfree(vq->split.desc_state); list_del(&_vq->list); kfree(vq); } diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c index e149e66a6ea9..e92f38fcb7a4 100644 --- a/drivers/watchdog/da9062_wdt.c +++ b/drivers/watchdog/da9062_wdt.c @@ -94,13 +94,6 @@ static int da9062_wdt_stop(struct watchdog_device *wdd) struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd); int ret; - ret = da9062_reset_watchdog_timer(wdt); - if (ret) { - dev_err(wdt->hw->dev, "Failed to ping the watchdog (err = %d)\n", - ret); - return ret; - } - ret = regmap_update_bits(wdt->hw->regmap, DA9062AA_CONTROL_D, DA9062AA_TWDSCALE_MASK, diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index 1ce39de917f0..88c5e6361aa0 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -54,6 +54,13 @@ module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +#define WDAT_DEFAULT_TIMEOUT 30 + +static int timeout = WDAT_DEFAULT_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=" + __MODULE_STRING(WDAT_DEFAULT_TIMEOUT) ")"); + static int wdat_wdt_read(struct wdat_wdt *wdat, const struct wdat_instruction *instr, u32 *value) { @@ -438,6 +445,22 @@ static int wdat_wdt_probe(struct platform_device *pdev) platform_set_drvdata(pdev, wdat); + /* + * Set initial timeout so that userspace has time to configure the + * watchdog properly after it has opened the device. In some cases + * the BIOS default is too short and causes immediate reboot. + */ + if (timeout * 1000 < wdat->wdd.min_hw_heartbeat_ms || + timeout * 1000 > wdat->wdd.max_hw_heartbeat_ms) { + dev_warn(dev, "Invalid timeout %d given, using %d\n", + timeout, WDAT_DEFAULT_TIMEOUT); + timeout = WDAT_DEFAULT_TIMEOUT; + } + + ret = wdat_wdt_set_timeout(&wdat->wdd, timeout); + if (ret) + return ret; + watchdog_set_nowayout(&wdat->wdd, nowayout); return devm_watchdog_register_device(dev, &wdat->wdd); } diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index d239fc3c5e3d..eb5151fc8efa 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c @@ -313,6 +313,8 @@ static int process_msg(void) req->msg.type = state.msg.type; req->msg.len = state.msg.len; req->body = state.body; + /* write body, then update state */ + virt_wmb(); req->state = xb_req_state_got_reply; req->cb(req); } else @@ -395,6 +397,8 @@ static int process_writes(void) if (state.req->state == xb_req_state_aborted) kfree(state.req); else { + /* write err, then update state */ + virt_wmb(); state.req->state = xb_req_state_got_reply; wake_up(&state.req->wq); } diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index ddc18da61834..3a06eb699f33 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -191,8 +191,11 @@ static bool xenbus_ok(void) static bool test_reply(struct xb_req_data *req) { - if (req->state == xb_req_state_got_reply || !xenbus_ok()) + if (req->state == xb_req_state_got_reply || !xenbus_ok()) { + /* read req->state before all other fields */ + virt_rmb(); return true; + } /* Make sure to reread req->state each time. */ barrier(); @@ -202,7 +205,7 @@ static bool test_reply(struct xb_req_data *req) static void *read_reply(struct xb_req_data *req) { - while (req->state != xb_req_state_got_reply) { + do { wait_event(req->wq, test_reply(req)); if (!xenbus_ok()) @@ -216,7 +219,7 @@ static void *read_reply(struct xb_req_data *req) if (req->err) return ERR_PTR(req->err); - } + } while (req->state != xb_req_state_got_reply); return req->body; } diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index b86195e4dc6c..b378cd780ed5 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -243,6 +243,17 @@ static void afs_cm_destructor(struct afs_call *call) call->buffer = NULL; } +/* + * Abort a service call from within an action function. + */ +static void afs_abort_service_call(struct afs_call *call, u32 abort_code, int error, + const char *why) +{ + rxrpc_kernel_abort_call(call->net->socket, call->rxcall, + abort_code, error, why); + afs_set_call_complete(call, error, 0); +} + /* * The server supplied a list of callbacks that it wanted to break. */ @@ -510,8 +521,7 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work) if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0) afs_send_empty_reply(call); else - rxrpc_kernel_abort_call(call->net->socket, call->rxcall, - 1, 1, "K-1"); + afs_abort_service_call(call, 1, 1, "K-1"); afs_put_call(call); _leave(""); diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c index cfe62b154f68..e1b9ed679045 100644 --- a/fs/afs/fs_probe.c +++ b/fs/afs/fs_probe.c @@ -145,6 +145,7 @@ static int afs_do_probe_fileserver(struct afs_net *net, read_lock(&server->fs_lock); ac.alist = rcu_dereference_protected(server->addresses, lockdep_is_held(&server->fs_lock)); + afs_get_addrlist(ac.alist); read_unlock(&server->fs_lock); atomic_set(&server->probe_outstanding, ac.alist->nr_addrs); @@ -163,6 +164,7 @@ static int afs_do_probe_fileserver(struct afs_net *net, if (!in_progress) afs_fs_probe_done(server); + afs_put_addrlist(ac.alist); return in_progress; } diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 759e0578012c..d5efb1debebf 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -154,7 +154,7 @@ struct afs_call { }; unsigned char unmarshall; /* unmarshalling phase */ unsigned char addr_ix; /* Address in ->alist */ - bool incoming; /* T if incoming call */ + bool drop_ref; /* T if need to drop ref for incoming call */ bool send_pages; /* T if data from mapping should be sent */ bool need_attention; /* T if RxRPC poked us */ bool async; /* T if asynchronous */ @@ -1203,8 +1203,16 @@ static inline void afs_set_call_complete(struct afs_call *call, ok = true; } spin_unlock_bh(&call->state_lock); - if (ok) + if (ok) { trace_afs_call_done(call); + + /* Asynchronous calls have two refs to release - one from the alloc and + * one queued with the work item - and we can't just deallocate the + * call because the work item may be queued again. + */ + if (call->drop_ref) + afs_put_call(call); + } } /* diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 61498d9f06ef..ef1d09f8920b 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -18,7 +18,6 @@ struct workqueue_struct *afs_async_calls; static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long); static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long); -static void afs_delete_async_call(struct work_struct *); static void afs_process_async_call(struct work_struct *); static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long); static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long); @@ -169,7 +168,7 @@ void afs_put_call(struct afs_call *call) int n = atomic_dec_return(&call->usage); int o = atomic_read(&net->nr_outstanding_calls); - trace_afs_call(call, afs_call_trace_put, n + 1, o, + trace_afs_call(call, afs_call_trace_put, n, o, __builtin_return_address(0)); ASSERTCMP(n, >=, 0); @@ -402,8 +401,10 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp) /* If the call is going to be asynchronous, we need an extra ref for * the call to hold itself so the caller need not hang on to its ref. */ - if (call->async) + if (call->async) { afs_get_call(call, afs_call_trace_get); + call->drop_ref = true; + } /* create a call */ rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key, @@ -584,8 +585,6 @@ static void afs_deliver_to_call(struct afs_call *call) done: if (call->type->done) call->type->done(call); - if (state == AFS_CALL_COMPLETE && call->incoming) - afs_put_call(call); out: _leave(""); return; @@ -604,11 +603,7 @@ call_complete: long afs_wait_for_call_to_complete(struct afs_call *call, struct afs_addr_cursor *ac) { - signed long rtt2, timeout; long ret; - bool stalled = false; - u64 rtt; - u32 life, last_life; bool rxrpc_complete = false; DECLARE_WAITQUEUE(myself, current); @@ -619,14 +614,6 @@ long afs_wait_for_call_to_complete(struct afs_call *call, if (ret < 0) goto out; - rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall); - rtt2 = nsecs_to_jiffies64(rtt) * 2; - if (rtt2 < 2) - rtt2 = 2; - - timeout = rtt2; - rxrpc_kernel_check_life(call->net->socket, call->rxcall, &last_life); - add_wait_queue(&call->waitq, &myself); for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); @@ -637,37 +624,19 @@ long afs_wait_for_call_to_complete(struct afs_call *call, call->need_attention = false; __set_current_state(TASK_RUNNING); afs_deliver_to_call(call); - timeout = rtt2; continue; } if (afs_check_call_state(call, AFS_CALL_COMPLETE)) break; - if (!rxrpc_kernel_check_life(call->net->socket, call->rxcall, &life)) { + if (!rxrpc_kernel_check_life(call->net->socket, call->rxcall)) { /* rxrpc terminated the call. */ rxrpc_complete = true; break; } - if (call->intr && timeout == 0 && - life == last_life && signal_pending(current)) { - if (stalled) - break; - __set_current_state(TASK_RUNNING); - rxrpc_kernel_probe_life(call->net->socket, call->rxcall); - timeout = rtt2; - stalled = true; - continue; - } - - if (life != last_life) { - timeout = rtt2; - last_life = life; - stalled = false; - } - - timeout = schedule_timeout(timeout); + schedule(); } remove_wait_queue(&call->waitq, &myself); @@ -735,7 +704,7 @@ static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall, u = atomic_fetch_add_unless(&call->usage, 1, 0); if (u != 0) { - trace_afs_call(call, afs_call_trace_wake, u, + trace_afs_call(call, afs_call_trace_wake, u + 1, atomic_read(&call->net->nr_outstanding_calls), __builtin_return_address(0)); @@ -744,21 +713,6 @@ static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall, } } -/* - * Delete an asynchronous call. The work item carries a ref to the call struct - * that we need to release. - */ -static void afs_delete_async_call(struct work_struct *work) -{ - struct afs_call *call = container_of(work, struct afs_call, async_work); - - _enter(""); - - afs_put_call(call); - - _leave(""); -} - /* * Perform I/O processing on an asynchronous call. The work item carries a ref * to the call struct that we either need to release or to pass on. @@ -774,16 +728,6 @@ static void afs_process_async_call(struct work_struct *work) afs_deliver_to_call(call); } - if (call->state == AFS_CALL_COMPLETE) { - /* We have two refs to release - one from the alloc and one - * queued with the work item - and we can't just deallocate the - * call because the work item may be queued again. - */ - call->async_work.func = afs_delete_async_call; - if (!queue_work(afs_async_calls, &call->async_work)) - afs_put_call(call); - } - afs_put_call(call); _leave(""); } @@ -810,6 +754,7 @@ void afs_charge_preallocation(struct work_struct *work) if (!call) break; + call->drop_ref = true; call->async = true; call->state = AFS_CALL_SV_AWAIT_OP_ID; init_waitqueue_head(&call->waitq); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 50feb01f27f3..94b0df3fb3c8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -8426,6 +8426,7 @@ static inline blk_status_t btrfs_lookup_and_bind_dio_csum(struct inode *inode, { struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); struct btrfs_io_bio *orig_io_bio = btrfs_io_bio(dip->orig_bio); + u16 csum_size; blk_status_t ret; /* @@ -8445,7 +8446,8 @@ static inline blk_status_t btrfs_lookup_and_bind_dio_csum(struct inode *inode, file_offset -= dip->logical_offset; file_offset >>= inode->i_sb->s_blocksize_bits; - io_bio->csum = (u8 *)(((u32 *)orig_io_bio->csum) + file_offset); + csum_size = btrfs_super_csum_size(btrfs_sb(inode->i_sb)->super_copy); + io_bio->csum = orig_io_bio->csum + csum_size * file_offset; return 0; } @@ -10140,6 +10142,10 @@ out_fail: ret = btrfs_sync_log(trans, BTRFS_I(old_inode)->root, &ctx); if (ret) commit_transaction = true; + } else if (sync_log) { + mutex_lock(&root->log_mutex); + list_del(&ctx.list); + mutex_unlock(&root->log_mutex); } if (commit_transaction) { ret = btrfs_commit_transaction(trans); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index cd09e63d682b..ce54a1b12819 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1415,10 +1415,13 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from) struct inode *inode = file_inode(file); struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_fs_client *fsc = ceph_inode_to_client(inode); + struct ceph_osd_client *osdc = &fsc->client->osdc; struct ceph_cap_flush *prealloc_cf; ssize_t count, written = 0; int err, want, got; bool direct_lock = false; + u32 map_flags; + u64 pool_flags; loff_t pos; loff_t limit = max(i_size_read(inode), fsc->max_file_size); @@ -1481,8 +1484,12 @@ retry_snap: goto out; } - /* FIXME: not complete since it doesn't account for being at quota */ - if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_FULL)) { + down_read(&osdc->lock); + map_flags = osdc->osdmap->flags; + pool_flags = ceph_pg_pool_flags(osdc->osdmap, ci->i_layout.pool_id); + up_read(&osdc->lock); + if ((map_flags & CEPH_OSDMAP_FULL) || + (pool_flags & CEPH_POOL_FLAG_FULL)) { err = -ENOSPC; goto out; } @@ -1575,7 +1582,8 @@ retry_snap: } if (written >= 0) { - if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_NEARFULL)) + if ((map_flags & CEPH_OSDMAP_NEARFULL) || + (pool_flags & CEPH_POOL_FLAG_NEARFULL)) iocb->ki_flags |= IOCB_DSYNC; written = generic_write_sync(iocb, written); } diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index ccfcc66aaf44..923be9399b21 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -1155,5 +1155,6 @@ void ceph_cleanup_snapid_map(struct ceph_mds_client *mdsc) pr_err("snapid map %llx -> %x still in use\n", sm->snap, sm->dev); } + kfree(sm); } } diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 606f26d862dc..cc3ada12848d 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -324,6 +324,8 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) if (full_path == NULL) goto cdda_exit; + convert_delimiter(full_path, '\\'); + cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path); if (!cifs_sb_master_tlink(cifs_sb)) { diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 637624ab6e46..115f063497ff 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -530,6 +530,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) if (tcon->seal) seq_puts(s, ",seal"); + else if (tcon->ses->server->ignore_signature) + seq_puts(s, ",signloosely"); if (tcon->nocase) seq_puts(s, ",nocase"); if (tcon->local_lease) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 53611d7e9d28..f9cbdfc1591b 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1229,6 +1229,7 @@ struct cifs_fid { __u64 volatile_fid; /* volatile file id for smb2 */ __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for smb2 */ __u8 create_guid[16]; + __u32 access; struct cifs_pending_open *pending_open; unsigned int epoch; #ifdef CONFIG_CIFS_DEBUG2 @@ -1700,6 +1701,12 @@ static inline bool is_retryable_error(int error) return false; } + +/* cifs_get_writable_file() flags */ +#define FIND_WR_ANY 0 +#define FIND_WR_FSUID_ONLY 1 +#define FIND_WR_WITH_DELETE 2 + #define MID_FREE 0 #define MID_REQUEST_ALLOCATED 1 #define MID_REQUEST_SUBMITTED 2 diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index fe597d3d5208..f18da99a6b55 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -133,11 +133,12 @@ extern bool backup_cred(struct cifs_sb_info *); extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, unsigned int bytes_written); -extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); +extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int); extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, - bool fsuid_only, + int flags, struct cifsFileInfo **ret_file); extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, + int flags, struct cifsFileInfo **ret_file); extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4f554f019a98..c8494fa5e19d 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1489,6 +1489,7 @@ openRetry: *oplock = rsp->OplockLevel; /* cifs fid stays in le */ oparms->fid->netfid = rsp->Fid; + oparms->fid->access = desired_access; /* Let caller know file was created so we can set the mode. */ /* Do we care about the CreateAction in any other cases? */ @@ -2112,7 +2113,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) wdata2->tailsz = tailsz; wdata2->bytes = cur_len; - rc = cifs_get_writable_file(CIFS_I(inode), false, + rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &wdata2->cfile); if (!wdata2->cfile) { cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n", diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7ce689d31aa2..5a35850ccb1a 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -560,7 +560,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, if (server->ops->close) server->ops->close(xid, tcon, &fid); cifs_del_pending_open(&open); - fput(file); rc = -ENOMEM; } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 969543034b4d..35c55cf38a35 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1173,7 +1173,8 @@ try_again: rc = posix_lock_file(file, flock, NULL); up_write(&cinode->lock_sem); if (rc == FILE_LOCK_DEFERRED) { - rc = wait_event_interruptible(flock->fl_wait, !flock->fl_blocker); + rc = wait_event_interruptible(flock->fl_wait, + list_empty(&flock->fl_blocked_member)); if (!rc) goto try_again; locks_delete_block(flock); @@ -1916,7 +1917,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, /* Return -EBADF if no handle is found and general rc otherwise */ int -cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only, +cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags, struct cifsFileInfo **ret_file) { struct cifsFileInfo *open_file, *inv_file = NULL; @@ -1924,7 +1925,8 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only, bool any_available = false; int rc = -EBADF; unsigned int refind = 0; - + bool fsuid_only = flags & FIND_WR_FSUID_ONLY; + bool with_delete = flags & FIND_WR_WITH_DELETE; *ret_file = NULL; /* @@ -1956,6 +1958,8 @@ refind_writable: continue; if (fsuid_only && !uid_eq(open_file->uid, current_fsuid())) continue; + if (with_delete && !(open_file->fid.access & DELETE)) + continue; if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { if (!open_file->invalidHandle) { /* found a good writable file */ @@ -2003,12 +2007,12 @@ refind_writable: } struct cifsFileInfo * -find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) +find_writable_file(struct cifsInodeInfo *cifs_inode, int flags) { struct cifsFileInfo *cfile; int rc; - rc = cifs_get_writable_file(cifs_inode, fsuid_only, &cfile); + rc = cifs_get_writable_file(cifs_inode, flags, &cfile); if (rc) cifs_dbg(FYI, "couldn't find writable handle rc=%d", rc); @@ -2017,6 +2021,7 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, + int flags, struct cifsFileInfo **ret_file) { struct list_head *tmp; @@ -2043,7 +2048,7 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, kfree(full_path); cinode = CIFS_I(d_inode(cfile->dentry)); spin_unlock(&tcon->open_file_lock); - return cifs_get_writable_file(cinode, 0, ret_file); + return cifs_get_writable_file(cinode, flags, ret_file); } spin_unlock(&tcon->open_file_lock); @@ -2120,7 +2125,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) if (mapping->host->i_size - offset < (loff_t)to) to = (unsigned)(mapping->host->i_size - offset); - rc = cifs_get_writable_file(CIFS_I(mapping->host), false, &open_file); + rc = cifs_get_writable_file(CIFS_I(mapping->host), FIND_WR_ANY, + &open_file); if (!rc) { bytes_written = cifs_write(open_file, open_file->pid, write_data, to - from, &offset); @@ -2313,7 +2319,7 @@ retry: if (cfile) cifsFileInfo_put(cfile); - rc = cifs_get_writable_file(CIFS_I(inode), false, &cfile); + rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile); /* in case of an error store it to return later */ if (rc) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index aafcd79c4772..7c5e983fe385 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -2011,6 +2011,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) struct inode *inode = d_inode(dentry); struct super_block *sb = dentry->d_sb; char *full_path = NULL; + int count = 0; if (inode == NULL) return -ENOENT; @@ -2032,15 +2033,18 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry) full_path, inode, inode->i_count.counter, dentry, cifs_get_time(dentry), jiffies); +again: if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); else rc = cifs_get_inode_info(&inode, full_path, NULL, sb, xid, NULL); - + if (rc == -EAGAIN && count++ < 10) + goto again; out: kfree(full_path); free_xid(xid); + return rc; } @@ -2216,7 +2220,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, * writebehind data than the SMB timeout for the SetPathInfo * request would allow */ - open_file = find_writable_file(cifsInode, true); + open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); if (open_file) { tcon = tlink_tcon(open_file->tlink); server = tcon->ses->server; @@ -2366,7 +2370,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) args->ctime = NO_CHANGE_64; args->device = 0; - open_file = find_writable_file(cifsInode, true); + open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); if (open_file) { u16 nfid = open_file->fid.netfid; u32 npid = open_file->pid; @@ -2469,7 +2473,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) rc = 0; if (attrs->ia_valid & ATTR_MTIME) { - rc = cifs_get_writable_file(cifsInode, false, &wfile); + rc = cifs_get_writable_file(cifsInode, FIND_WR_ANY, &wfile); if (!rc) { tcon = tlink_tcon(wfile->tlink); rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid); diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 514810694c0f..195766221a7a 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -767,7 +767,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, struct cifs_tcon *tcon; /* if the file is already open for write, just use that fileid */ - open_file = find_writable_file(cinode, true); + open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY); if (open_file) { fid.netfid = open_file->fid.netfid; netpid = open_file->pid; diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c index 4121ac1163ca..f2a6f7f28340 100644 --- a/fs/cifs/smb2inode.c +++ b/fs/cifs/smb2inode.c @@ -525,7 +525,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name, cifs_i = CIFS_I(inode); dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; data.Attributes = cpu_to_le32(dosattrs); - cifs_get_writable_path(tcon, name, &cfile); + cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile); tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, FILE_WRITE_ATTRIBUTES, FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE, @@ -581,7 +581,7 @@ smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon, { struct cifsFileInfo *cfile; - cifs_get_writable_path(tcon, from_name, &cfile); + cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile); return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, DELETE, SMB2_OP_RENAME, cfile); diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index b75d208d4b2b..76eacffb24d8 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -1338,6 +1338,7 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock) cfile->fid.persistent_fid = fid->persistent_fid; cfile->fid.volatile_fid = fid->volatile_fid; + cfile->fid.access = fid->access; #ifdef CONFIG_CIFS_DEBUG2 cfile->fid.mid = fid->mid; #endif /* CIFS_DEBUG2 */ @@ -3162,7 +3163,7 @@ static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offs * some servers (Windows2016) will not reflect recent writes in * QUERY_ALLOCATED_RANGES until SMB2_flush is called. */ - wrcfile = find_writable_file(cifsi, false); + wrcfile = find_writable_file(cifsi, FIND_WR_ANY); if (wrcfile) { filemap_write_and_wait(inode->i_mapping); smb2_flush_file(xid, tcon, &wrcfile->fid); @@ -3251,7 +3252,7 @@ static int smb3_fiemap(struct cifs_tcon *tcon, if (rc) goto out; - if (out_data_len < sizeof(struct file_allocated_range_buffer)) { + if (out_data_len && out_data_len < sizeof(struct file_allocated_range_buffer)) { rc = -EINVAL; goto out; } diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index c6fc6582ee7b..c8f304cae3f3 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2650,6 +2650,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, atomic_inc(&tcon->num_remote_opens); oparms->fid->persistent_fid = rsp->PersistentFileId; oparms->fid->volatile_fid = rsp->VolatileFileId; + oparms->fid->access = oparms->desired_access; #ifdef CONFIG_CIFS_DEBUG2 oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId); #endif /* CIFS_DEBUG2 */ diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index aee34faa05c6..e3cff3c6988f 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -78,6 +78,26 @@ static inline int fscrypt_context_size(const union fscrypt_context *ctx) return 0; } +/* Check whether an fscrypt_context has a recognized version number and size */ +static inline bool fscrypt_context_is_valid(const union fscrypt_context *ctx, + int ctx_size) +{ + return ctx_size >= 1 && ctx_size == fscrypt_context_size(ctx); +} + +/* Retrieve the context's nonce, assuming the context was already validated */ +static inline const u8 *fscrypt_context_nonce(const union fscrypt_context *ctx) +{ + switch (ctx->version) { + case FSCRYPT_CONTEXT_V1: + return ctx->v1.nonce; + case FSCRYPT_CONTEXT_V2: + return ctx->v2.nonce; + } + WARN_ON(1); + return NULL; +} + #undef fscrypt_policy union fscrypt_policy { u8 version; diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 04c86e489a7a..34f95cd6c8eb 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -494,20 +494,8 @@ int fscrypt_get_encryption_info(struct inode *inode) goto out; } - switch (ctx.version) { - case FSCRYPT_CONTEXT_V1: - memcpy(crypt_info->ci_nonce, ctx.v1.nonce, - FS_KEY_DERIVATION_NONCE_SIZE); - break; - case FSCRYPT_CONTEXT_V2: - memcpy(crypt_info->ci_nonce, ctx.v2.nonce, - FS_KEY_DERIVATION_NONCE_SIZE); - break; - default: - WARN_ON(1); - res = -EINVAL; - goto out; - } + memcpy(crypt_info->ci_nonce, fscrypt_context_nonce(&ctx), + FS_KEY_DERIVATION_NONCE_SIZE); if (!fscrypt_supported_policy(&crypt_info->ci_policy, inode)) { res = -EINVAL; @@ -607,6 +595,15 @@ int fscrypt_drop_inode(struct inode *inode) return 0; mk = ci->ci_master_key->payload.data[0]; + /* + * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes + * protected by the key were cleaned by sync_filesystem(). But if + * userspace is still using the files, inodes can be dirtied between + * then and now. We mustn't lose any writes, so skip dirty inodes here. + */ + if (inode->i_state & I_DIRTY_ALL) + return 0; + /* * Note: since we aren't holding ->mk_secret_sem, the result here can * immediately become outdated. But there's no correctness problem with diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index cf2a9d26ef7d..10ccf945020c 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -258,7 +258,7 @@ int fscrypt_policy_from_context(union fscrypt_policy *policy_u, { memset(policy_u, 0, sizeof(*policy_u)); - if (ctx_size <= 0 || ctx_size != fscrypt_context_size(ctx_u)) + if (!fscrypt_context_is_valid(ctx_u, ctx_size)) return -EINVAL; switch (ctx_u->version) { @@ -481,6 +481,25 @@ int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg) } EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_policy_ex); +/* FS_IOC_GET_ENCRYPTION_NONCE: retrieve file's encryption nonce for testing */ +int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg) +{ + struct inode *inode = file_inode(filp); + union fscrypt_context ctx; + int ret; + + ret = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx)); + if (ret < 0) + return ret; + if (!fscrypt_context_is_valid(&ctx, ret)) + return -EINVAL; + if (copy_to_user(arg, fscrypt_context_nonce(&ctx), + FS_KEY_DERIVATION_NONCE_SIZE)) + return -EFAULT; + return 0; +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_nonce); + /** * fscrypt_has_permitted_context() - is a file's encryption policy permitted * within its directory? diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 6730d92e225a..f9ba8e6c2f86 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1882,9 +1882,9 @@ fetch_events: waiter = true; init_waitqueue_entry(&wait, current); - spin_lock_irq(&ep->wq.lock); + write_lock_irq(&ep->lock); __add_wait_queue_exclusive(&ep->wq, &wait); - spin_unlock_irq(&ep->wq.lock); + write_unlock_irq(&ep->lock); } for (;;) { @@ -1933,9 +1933,9 @@ send_events: goto fetch_events; if (waiter) { - spin_lock_irq(&ep->wq.lock); + write_lock_irq(&ep->lock); __remove_wait_queue(&ep->wq, &wait); - spin_unlock_irq(&ep->wq.lock); + write_unlock_irq(&ep->lock); } return res; diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index ef280d7249ca..a05916c5cfbc 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -1210,6 +1210,11 @@ resizefs_out: return -EOPNOTSUPP; return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_NONCE: + if (!ext4_has_feature_encrypt(sb)) + return -EOPNOTSUPP; + return fscrypt_ioctl_get_nonce(filp, (void __user *)arg); + case EXT4_IOC_CLEAR_ES_CACHE: { if (!inode_owner_or_capable(inode)) @@ -1369,6 +1374,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + case FS_IOC_GET_ENCRYPTION_NONCE: case EXT4_IOC_SHUTDOWN: case FS_IOC_GETFSMAP: case FS_IOC_ENABLE_VERITY: diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index c0b4b9fbe2e0..bc200cf33bb9 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -1787,12 +1787,15 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id) static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) { struct f2fs_inode_info *fi = F2FS_I(inode); + u32 masked_flags = fi->i_flags & mask; + + f2fs_bug_on(F2FS_I_SB(inode), (iflags & ~mask)); /* Is it quota file? Do not allow user to mess with it */ if (IS_NOQUOTA(inode)) return -EPERM; - if ((iflags ^ fi->i_flags) & F2FS_CASEFOLD_FL) { + if ((iflags ^ masked_flags) & F2FS_CASEFOLD_FL) { if (!f2fs_sb_has_casefold(F2FS_I_SB(inode))) return -EOPNOTSUPP; if (!f2fs_empty_dir(inode)) @@ -1806,9 +1809,9 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) return -EINVAL; } - if ((iflags ^ fi->i_flags) & F2FS_COMPR_FL) { + if ((iflags ^ masked_flags) & F2FS_COMPR_FL) { if (S_ISREG(inode->i_mode) && - (fi->i_flags & F2FS_COMPR_FL || i_size_read(inode) || + (masked_flags & F2FS_COMPR_FL || i_size_read(inode) || F2FS_HAS_BLOCKS(inode))) return -EINVAL; if (iflags & F2FS_NOCOMP_FL) @@ -1825,8 +1828,8 @@ static int f2fs_setflags_common(struct inode *inode, u32 iflags, u32 mask) set_compress_context(inode); } } - if ((iflags ^ fi->i_flags) & F2FS_NOCOMP_FL) { - if (fi->i_flags & F2FS_COMPR_FL) + if ((iflags ^ masked_flags) & F2FS_NOCOMP_FL) { + if (masked_flags & F2FS_COMPR_FL) return -EINVAL; } @@ -2423,6 +2426,14 @@ static int f2fs_ioc_get_encryption_key_status(struct file *filp, return fscrypt_ioctl_get_key_status(filp, (void __user *)arg); } +static int f2fs_ioc_get_encryption_nonce(struct file *filp, unsigned long arg) +{ + if (!f2fs_sb_has_encrypt(F2FS_I_SB(file_inode(filp)))) + return -EOPNOTSUPP; + + return fscrypt_ioctl_get_nonce(filp, (void __user *)arg); +} + static int f2fs_ioc_gc(struct file *filp, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -3437,6 +3448,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_ioc_remove_encryption_key_all_users(filp, arg); case FS_IOC_GET_ENCRYPTION_KEY_STATUS: return f2fs_ioc_get_encryption_key_status(filp, arg); + case FS_IOC_GET_ENCRYPTION_NONCE: + return f2fs_ioc_get_encryption_nonce(filp, arg); case F2FS_IOC_GARBAGE_COLLECT: return f2fs_ioc_gc(filp, arg); case F2FS_IOC_GARBAGE_COLLECT_RANGE: @@ -3610,6 +3623,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + case FS_IOC_GET_ENCRYPTION_NONCE: case F2FS_IOC_GARBAGE_COLLECT: case F2FS_IOC_GARBAGE_COLLECT_RANGE: case F2FS_IOC_WRITE_CHECKPOINT: diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 5f04c5c810fb..d40cbad16659 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -749,6 +749,13 @@ static struct inode *fat_alloc_inode(struct super_block *sb) return NULL; init_rwsem(&ei->truncate_lock); + /* Zeroing to allow iput() even if partial initialized inode. */ + ei->mmu_private = 0; + ei->i_start = 0; + ei->i_logstart = 0; + ei->i_attrs = 0; + ei->i_pos = 0; + return &ei->vfs_inode; } @@ -1373,16 +1380,6 @@ out: return 0; } -static void fat_dummy_inode_init(struct inode *inode) -{ - /* Initialize this dummy inode to work as no-op. */ - MSDOS_I(inode)->mmu_private = 0; - MSDOS_I(inode)->i_start = 0; - MSDOS_I(inode)->i_logstart = 0; - MSDOS_I(inode)->i_attrs = 0; - MSDOS_I(inode)->i_pos = 0; -} - static int fat_read_root(struct inode *inode) { struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); @@ -1843,13 +1840,11 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, fat_inode = new_inode(sb); if (!fat_inode) goto out_fail; - fat_dummy_inode_init(fat_inode); sbi->fat_inode = fat_inode; fsinfo_inode = new_inode(sb); if (!fsinfo_inode) goto out_fail; - fat_dummy_inode_init(fsinfo_inode); fsinfo_inode->i_ino = MSDOS_FSINFO_INO; sbi->fsinfo_inode = fsinfo_inode; insert_inode_hash(fsinfo_inode); diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ed1abc9e33cf..4f2e4f38feb8 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -276,12 +276,10 @@ static void flush_bg_queue(struct fuse_conn *fc) void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) { struct fuse_iqueue *fiq = &fc->iq; - bool async; if (test_and_set_bit(FR_FINISHED, &req->flags)) goto put_request; - async = req->args->end; /* * test_and_set_bit() implies smp_mb() between bit * changing and below intr_entry check. Pairs with @@ -324,7 +322,7 @@ void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) wake_up(&req->waitq); } - if (async) + if (test_bit(FR_ASYNC, &req->flags)) req->args->end(fc, req->args, req->out.h.error); put_request: fuse_put_request(fc, req); @@ -471,6 +469,8 @@ static void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args) req->in.h.opcode = args->opcode; req->in.h.nodeid = args->nodeid; req->args = args; + if (args->end) + __set_bit(FR_ASYNC, &req->flags); } ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index aa75e2305b75..ca344bf71404 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -301,6 +301,7 @@ struct fuse_io_priv { * FR_SENT: request is in userspace, waiting for an answer * FR_FINISHED: request is finished * FR_PRIVATE: request is on private list + * FR_ASYNC: request is asynchronous */ enum fuse_req_flag { FR_ISREPLY, @@ -314,6 +315,7 @@ enum fuse_req_flag { FR_SENT, FR_FINISHED, FR_PRIVATE, + FR_ASYNC, }; /** diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index e1e18fb587eb..8466166f22e3 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1248,7 +1248,7 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry, if (!(file->f_mode & FMODE_OPENED)) return finish_no_open(file, d); dput(d); - return 0; + return excl && (flags & O_CREAT) ? -EEXIST : 0; } BUG_ON(d != NULL); diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index 91a81a571d51..6661ac3b52da 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -118,8 +118,8 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) error = mutex_lock_interruptible(&bfc->bc_mutex); if (error) goto out; - error = incfs_read_file_header(bfc, &df->df_metadata_off, - &df->df_id, &size); + error = incfs_read_file_header(bfc, &df->df_metadata_off, &df->df_id, + &size, &df->df_header_flags); mutex_unlock(&bfc->bc_mutex); if (error) @@ -127,7 +127,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) df->df_size = size; if (size > 0) - df->df_block_count = get_blocks_count_for_size(size); + df->df_data_block_count = get_blocks_count_for_size(size); md_records = incfs_scan_metadata_chain(df); if (md_records < 0) @@ -250,7 +250,7 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, { u8 digest[INCFS_MAX_HASH_SIZE] = {}; struct mtree *tree = NULL; - struct ondisk_signature *sig = NULL; + struct incfs_df_signature *sig = NULL; struct mem_range calc_digest_rng; struct mem_range saved_digest_rng; struct mem_range root_hash_rng; @@ -273,8 +273,8 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, return res; for (lvl = 0; lvl < tree->depth; lvl++) { - loff_t lvl_off = tree->hash_level_suboffset[lvl] + - sig->mtree_offset; + loff_t lvl_off = + tree->hash_level_suboffset[lvl] + sig->hash_offset; loff_t hash_block_off = lvl_off + round_down(hash_block_index * digest_size, INCFS_DATA_FILE_BLOCK_SIZE); @@ -322,72 +322,6 @@ static int validate_hash_tree(struct file *bf, struct data_file *df, return 0; } -static int revalidate_signature(struct file *bf, struct data_file *df) -{ - struct ondisk_signature *sig = df->df_signature; - struct mem_range root_hash = {}; - int result = 0; - u8 *sig_buf = NULL; - u8 *add_data_buf = NULL; - ssize_t read_res; - - /* File has no signature. */ - if (!sig || !df->df_hash_tree || sig->sig_size == 0) - return 0; - - /* Signature has already been validated. */ - if (df->df_signature_validated) - return 0; - - add_data_buf = kzalloc(sig->add_data_size, GFP_NOFS); - if (!add_data_buf) { - result = -ENOMEM; - goto out; - } - - read_res = incfs_kread(bf, add_data_buf, sig->add_data_size, - sig->add_data_offset); - if (read_res < 0) { - result = read_res; - goto out; - } - if (read_res != sig->add_data_size) { - result = -EIO; - goto out; - } - - sig_buf = kzalloc(sig->sig_size, GFP_NOFS); - if (!sig_buf) { - result = -ENOMEM; - goto out; - } - - read_res = incfs_kread(bf, sig_buf, sig->sig_size, sig->sig_offset); - if (read_res < 0) { - result = read_res; - goto out; - } - if (read_res != sig->sig_size) { - result = -EIO; - goto out; - } - - root_hash = range(df->df_hash_tree->root_hash, - df->df_hash_tree->alg->digest_size); - - result = incfs_validate_pkcs7_signature( - range(sig_buf, sig->sig_size), - root_hash, - range(add_data_buf, sig->add_data_size)); - - if (result == 0) - df->df_signature_validated = true; -out: - kfree(sig_buf); - kfree(add_data_buf); - return result; -} - static struct data_file_segment *get_file_segment(struct data_file *df, int block_index) { @@ -417,7 +351,7 @@ static int get_data_file_block(struct data_file *df, int index, blockmap_off = df->df_blockmap_off; bfc = df->df_backing_file_context; - if (index < 0 || index >= df->df_block_count || blockmap_off == 0) + if (index < 0 || blockmap_off == 0) return -EINVAL; error = incfs_read_blockmap_entry(bfc, index, blockmap_off, &bme); @@ -437,6 +371,96 @@ static int get_data_file_block(struct data_file *df, int index, return 0; } +static int copy_one_range(struct incfs_filled_range *range, void __user *buffer, + u32 size, u32 *size_out) +{ + if (*size_out + sizeof(*range) > size) + return -ERANGE; + + if (copy_to_user(((char *)buffer) + *size_out, range, sizeof(*range))) + return -EFAULT; + + *size_out += sizeof(*range); + return 0; +} + +int incfs_get_filled_blocks(struct data_file *df, + struct incfs_get_filled_blocks_args *arg) +{ + int error = 0; + bool in_range = false; + struct incfs_filled_range range; + void *buffer = u64_to_user_ptr(arg->range_buffer); + u32 size = arg->range_buffer_size; + u32 end_index = + arg->end_index ? arg->end_index : df->df_total_block_count; + u32 *size_out = &arg->range_buffer_size_out; + + *size_out = 0; + if (end_index > df->df_total_block_count) + end_index = df->df_total_block_count; + arg->total_blocks_out = df->df_total_block_count; + + if (df->df_header_flags & INCFS_FILE_COMPLETE) { + pr_debug("File marked full, fast get_filled_blocks"); + if (arg->start_index > end_index) { + arg->index_out = arg->start_index; + return 0; + } + + range = (struct incfs_filled_range){ + .begin = arg->start_index, + .end = end_index, + }; + + arg->index_out = end_index; + return copy_one_range(&range, buffer, size, size_out); + } + + for (arg->index_out = arg->start_index; arg->index_out < end_index; + ++arg->index_out) { + struct data_file_block dfb; + + error = get_data_file_block(df, arg->index_out, &dfb); + if (error) + break; + + if (is_data_block_present(&dfb) == in_range) + continue; + + if (!in_range) { + in_range = true; + range.begin = arg->index_out; + } else { + range.end = arg->index_out; + error = copy_one_range(&range, buffer, size, size_out); + if (error) + break; + in_range = false; + } + } + + if (in_range) { + range.end = arg->index_out; + error = copy_one_range(&range, buffer, size, size_out); + } + + if (!error && in_range && arg->start_index == 0 && + end_index == df->df_total_block_count && + *size_out == sizeof(struct incfs_filled_range)) { + int result; + + df->df_header_flags |= INCFS_FILE_COMPLETE; + result = incfs_update_file_header_flags( + df->df_backing_file_context, df->df_header_flags); + + /* Log failure only, since it's just a failed optimization */ + pr_debug("Marked file full with result %d", result); + } + + return error; +} + static bool is_read_done(struct pending_read *read) { return atomic_read_acquire(&read->done) != 0; @@ -536,7 +560,7 @@ static int wait_for_data_block(struct data_file *df, int block_index, if (!df || !res_block) return -EFAULT; - if (block_index < 0 || block_index >= df->df_block_count) + if (block_index < 0 || block_index >= df->df_data_block_count) return -EINVAL; if (df->df_blockmap_off <= 0) @@ -683,13 +707,6 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct data_file *df, result = err; } - if (result > 0) { - int err = revalidate_signature(bf, df); - - if (err < 0) - result = err; - } - if (result >= 0) log_block_read(mi, &df->df_id, index, false /*timed out*/); @@ -698,7 +715,7 @@ out: } int incfs_process_new_data_block(struct data_file *df, - struct incfs_new_data_block *block, u8 *data) + struct incfs_fill_block *block, u8 *data) { struct mount_info *mi = NULL; struct backing_file_context *bfc = NULL; @@ -713,7 +730,7 @@ int incfs_process_new_data_block(struct data_file *df, bfc = df->df_backing_file_context; mi = df->df_mount_info; - if (block->block_index >= df->df_block_count) + if (block->block_index >= df->df_data_block_count) return -ERANGE; segment = get_file_segment(df, block->block_index); @@ -755,7 +772,7 @@ unlock: int incfs_read_file_signature(struct data_file *df, struct mem_range dst) { struct file *bf = df->df_backing_file_context->bc_file; - struct ondisk_signature *sig; + struct incfs_df_signature *sig; int read_res = 0; if (!dst.data) @@ -780,12 +797,12 @@ int incfs_read_file_signature(struct data_file *df, struct mem_range dst) } int incfs_process_new_hash_block(struct data_file *df, - struct incfs_new_data_block *block, u8 *data) + struct incfs_fill_block *block, u8 *data) { struct backing_file_context *bfc = NULL; struct mount_info *mi = NULL; struct mtree *hash_tree = NULL; - struct ondisk_signature *sig = NULL; + struct incfs_df_signature *sig = NULL; loff_t hash_area_base = 0; loff_t hash_area_size = 0; int error = 0; @@ -804,11 +821,11 @@ int incfs_process_new_hash_block(struct data_file *df, hash_tree = df->df_hash_tree; sig = df->df_signature; - if (!hash_tree || !sig || sig->mtree_offset == 0) + if (!hash_tree || !sig || sig->hash_offset == 0) return -ENOTSUPP; - hash_area_base = sig->mtree_offset; - hash_area_size = sig->mtree_size; + hash_area_base = sig->hash_offset; + hash_area_size = sig->hash_size; if (hash_area_size < block->block_index * INCFS_DATA_FILE_BLOCK_SIZE + block->data_len) { /* Hash block goes beyond dedicated hash area of this file. */ @@ -819,7 +836,7 @@ int incfs_process_new_hash_block(struct data_file *df, if (!error) error = incfs_write_hash_block_to_backing_file( bfc, range(data, block->data_len), block->block_index, - hash_area_base); + hash_area_base, df->df_blockmap_off, df->df_size); mutex_unlock(&bfc->bc_mutex); return error; } @@ -835,9 +852,10 @@ static int process_blockmap_md(struct incfs_blockmap *bm, if (!df) return -EFAULT; - if (df->df_block_count != block_count) + if (df->df_data_block_count > block_count) return -EBADMSG; + df->df_total_block_count = block_count; df->df_blockmap_off = base_off; return error; } @@ -866,58 +884,69 @@ static int process_file_signature_md(struct incfs_file_signature *sg, { struct data_file *df = handler->context; struct mtree *hash_tree = NULL; - struct ondisk_signature *signature = NULL; int error = 0; - loff_t base_tree_off = le64_to_cpu(sg->sg_hash_tree_offset); - u32 tree_size = le32_to_cpu(sg->sg_hash_tree_size); - loff_t sig_off = le64_to_cpu(sg->sg_sig_offset); - u32 sig_size = le32_to_cpu(sg->sg_sig_size); - loff_t add_data_off = le64_to_cpu(sg->sg_add_data_offset); - u32 add_data_size = le32_to_cpu(sg->sg_add_data_size); + struct incfs_df_signature *signature = + kzalloc(sizeof(*signature), GFP_NOFS); + void *buf = NULL; + ssize_t read; - if (!df) - return -ENOENT; + if (!df || !df->df_backing_file_context || + !df->df_backing_file_context->bc_file) { + error = -ENOENT; + goto out; + } - signature = kzalloc(sizeof(*signature), GFP_NOFS); - if (!signature) { + signature->hash_offset = le64_to_cpu(sg->sg_hash_tree_offset); + signature->hash_size = le32_to_cpu(sg->sg_hash_tree_size); + signature->sig_offset = le64_to_cpu(sg->sg_sig_offset); + signature->sig_size = le32_to_cpu(sg->sg_sig_size); + + buf = kzalloc(signature->sig_size, GFP_NOFS); + if (!buf) { error = -ENOMEM; goto out; } - signature->add_data_offset = add_data_off; - signature->add_data_size = add_data_size; - signature->sig_offset = sig_off; - signature->sig_size = sig_size; - signature->mtree_offset = base_tree_off; - signature->mtree_size = tree_size; + read = incfs_kread(df->df_backing_file_context->bc_file, buf, + signature->sig_size, signature->sig_offset); + if (read < 0) { + error = read; + goto out; + } - hash_tree = incfs_alloc_mtree(sg->sg_hash_alg, df->df_block_count, - range(sg->sg_root_hash, sizeof(sg->sg_root_hash))); + if (read != signature->sig_size) { + error = -EINVAL; + goto out; + } + + hash_tree = incfs_alloc_mtree(range(buf, signature->sig_size), + df->df_data_block_count); if (IS_ERR(hash_tree)) { error = PTR_ERR(hash_tree); hash_tree = NULL; goto out; } - if (hash_tree->hash_tree_area_size != tree_size) { + if (hash_tree->hash_tree_area_size != signature->hash_size) { error = -EINVAL; goto out; } - if (tree_size > 0 && handler->md_record_offset <= base_tree_off) { + if (signature->hash_size > 0 && + handler->md_record_offset <= signature->hash_offset) { error = -EINVAL; goto out; } - if (handler->md_record_offset <= signature->add_data_offset || - handler->md_record_offset <= signature->sig_offset) { + if (handler->md_record_offset <= signature->sig_offset) { error = -EINVAL; goto out; } df->df_hash_tree = hash_tree; + hash_tree = NULL; df->df_signature = signature; + signature = NULL; out: - if (error) { - incfs_free_mtree(hash_tree); - kfree(signature); - } + incfs_free_mtree(hash_tree); + kfree(signature); + kfree(buf); return error; } @@ -973,6 +1002,17 @@ int incfs_scan_metadata_chain(struct data_file *df) result = records_count; } mutex_unlock(&bfc->bc_mutex); + + if (df->df_hash_tree) { + int hash_block_count = get_blocks_count_for_size( + df->df_hash_tree->hash_tree_area_size); + + if (df->df_data_block_count + hash_block_count != + df->df_total_block_count) + result = -EINVAL; + } else if (df->df_data_block_count != df->df_total_block_count) + result = -EINVAL; + out: kfree(handler); return result; diff --git a/fs/incfs/data_mgmt.h b/fs/incfs/data_mgmt.h index e86951c7845a..bd9b63af920e 100644 --- a/fs/incfs/data_mgmt.h +++ b/fs/incfs/data_mgmt.h @@ -183,16 +183,20 @@ struct data_file { /* File size in bytes */ loff_t df_size; - int df_block_count; /* File size in DATA_FILE_BLOCK_SIZE blocks */ + /* File header flags */ + u32 df_header_flags; + + /* File size in DATA_FILE_BLOCK_SIZE blocks */ + int df_data_block_count; + + /* Total number of blocks, data + hash */ + int df_total_block_count; struct file_attr n_attr; struct mtree *df_hash_tree; - struct ondisk_signature *df_signature; - - /* True, if file signature has already been validated. */ - bool df_signature_validated; + struct incfs_df_signature *df_signature; }; struct dir_file { @@ -233,14 +237,16 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct data_file *df, int index, int timeout_ms, struct mem_range tmp); +int incfs_get_filled_blocks(struct data_file *df, + struct incfs_get_filled_blocks_args *arg); + int incfs_read_file_signature(struct data_file *df, struct mem_range dst); int incfs_process_new_data_block(struct data_file *df, - struct incfs_new_data_block *block, u8 *data); + struct incfs_fill_block *block, u8 *data); int incfs_process_new_hash_block(struct data_file *df, - struct incfs_new_data_block *block, u8 *data); - + struct incfs_fill_block *block, u8 *data); bool incfs_fresh_pending_reads_exist(struct mount_info *mi, int last_number); diff --git a/fs/incfs/format.c b/fs/incfs/format.c index db71f527cf36..96f4e3d54f58 100644 --- a/fs/incfs/format.c +++ b/fs/incfs/format.c @@ -13,6 +13,7 @@ #include #include "format.h" +#include "data_mgmt.h" struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) { @@ -214,12 +215,23 @@ static int append_md_to_backing_file(struct backing_file_context *bfc, return result; } +int incfs_update_file_header_flags(struct backing_file_context *bfc, u32 flags) +{ + if (!bfc) + return -EFAULT; + + return write_to_bf(bfc, &flags, sizeof(flags), + offsetof(struct incfs_file_header, + fh_file_header_flags), + false); +} + /* * Reserve 0-filled space for the blockmap body, and append * incfs_blockmap metadata record pointing to it. */ int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc, - u32 block_count, loff_t *map_base_off) + u32 block_count) { struct incfs_blockmap blockmap = {}; int result = 0; @@ -245,12 +257,9 @@ int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc, /* Write blockmap metadata record pointing to the body written above. */ blockmap.m_base_offset = cpu_to_le64(file_end); result = append_md_to_backing_file(bfc, &blockmap.m_header); - if (result) { + if (result) /* Error, rollback file changes */ truncate_backing_file(bfc, file_end); - } else if (map_base_off) { - *map_base_off = file_end; - } return result; } @@ -299,9 +308,7 @@ int incfs_write_file_attr_to_backing_file(struct backing_file_context *bfc, } int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, - u8 hash_alg, u32 tree_size, - struct mem_range root_hash, struct mem_range add_data, - struct mem_range sig) + struct mem_range sig, u32 tree_size) { struct incfs_file_signature sg = {}; int result = 0; @@ -311,8 +318,6 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, if (!bfc) return -EFAULT; - if (root_hash.len > sizeof(sg.sg_root_hash)) - return -E2BIG; LOCK_REQUIRED(bfc->bc_mutex); @@ -321,7 +326,6 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, sg.sg_header.h_md_entry_type = INCFS_MD_SIGNATURE; sg.sg_header.h_record_size = cpu_to_le16(sizeof(sg)); sg.sg_header.h_next_md_offset = cpu_to_le64(0); - sg.sg_hash_alg = hash_alg; if (sig.data != NULL && sig.len > 0) { loff_t pos = incfs_get_end_offset(bfc->bc_file); @@ -333,20 +337,8 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, goto err; } - if (add_data.len > 0) { - loff_t pos = incfs_get_end_offset(bfc->bc_file); - - sg.sg_add_data_size = cpu_to_le32(add_data.len); - sg.sg_add_data_offset = cpu_to_le64(pos); - - result = write_to_bf(bfc, add_data.data, - add_data.len, pos, false); - if (result) - goto err; - } - tree_area_pos = incfs_get_end_offset(bfc->bc_file); - if (hash_alg && tree_size > 0) { + if (tree_size > 0) { if (tree_size > 5 * INCFS_DATA_FILE_BLOCK_SIZE) { /* * If hash tree is big enough, it makes sense to @@ -369,7 +361,6 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, sg.sg_hash_tree_size = cpu_to_le32(tree_size); sg.sg_hash_tree_offset = cpu_to_le64(tree_area_pos); } - memcpy(sg.sg_root_hash, root_hash.data, root_hash.len); /* Write a hash tree metadata record pointing to the hash tree above. */ result = append_md_to_backing_file(bfc, &sg.sg_header); @@ -456,12 +447,19 @@ int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc, } int incfs_write_hash_block_to_backing_file(struct backing_file_context *bfc, - struct mem_range block, - int block_index, loff_t hash_area_off) + struct mem_range block, + int block_index, + loff_t hash_area_off, + loff_t bm_base_off, int file_size) { + struct incfs_blockmap_entry bm_entry = {}; + int result; loff_t data_offset = 0; loff_t file_end = 0; - + loff_t bm_entry_off = + bm_base_off + + sizeof(struct incfs_blockmap_entry) * + (block_index + get_blocks_count_for_size(file_size)); if (!bfc) return -EFAULT; @@ -475,7 +473,17 @@ int incfs_write_hash_block_to_backing_file(struct backing_file_context *bfc, return -EINVAL; } - return write_to_bf(bfc, block.data, block.len, data_offset, false); + result = write_to_bf(bfc, block.data, block.len, data_offset, false); + if (result) + return result; + + bm_entry.me_data_offset_lo = cpu_to_le32((u32)data_offset); + bm_entry.me_data_offset_hi = cpu_to_le16((u16)(data_offset >> 32)); + bm_entry.me_data_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE); + bm_entry.me_flags = cpu_to_le16(INCFS_BLOCK_HASH); + + return write_to_bf(bfc, &bm_entry, sizeof(bm_entry), bm_entry_off, + false); } /* Initialize a new image in a given backing file. */ @@ -535,10 +543,9 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, return 0; } - int incfs_read_file_header(struct backing_file_context *bfc, loff_t *first_md_off, incfs_uuid_t *uuid, - u64 *file_size) + u64 *file_size, u32 *flags) { ssize_t bytes_read = 0; struct incfs_file_header fh = {}; @@ -572,6 +579,8 @@ int incfs_read_file_header(struct backing_file_context *bfc, *uuid = fh.fh_uuid; if (file_size) *file_size = le64_to_cpu(fh.fh_file_size); + if (flags) + *flags = le32_to_cpu(fh.fh_file_header_flags); return 0; } diff --git a/fs/incfs/format.h b/fs/incfs/format.h index a86881482e19..33e5ea4eba56 100644 --- a/fs/incfs/format.h +++ b/fs/incfs/format.h @@ -121,6 +121,10 @@ enum incfs_metadata_type { INCFS_MD_SIGNATURE = 3 }; +enum incfs_file_header_flags { + INCFS_FILE_COMPLETE = 1 << 0, +}; + /* Header included at the beginning of all metadata records on the disk. */ struct incfs_md_header { __u8 h_md_entry_type; @@ -159,8 +163,8 @@ struct incfs_file_header { /* INCFS_DATA_FILE_BLOCK_SIZE */ __le16 fh_data_block_size; - /* Padding, also reserved for future use. */ - __le32 fh_dummy; + /* File flags, from incfs_file_header_flags */ + __le32 fh_file_header_flags; /* Offset of the first metadata record */ __le64 fh_first_md_offset; @@ -178,6 +182,7 @@ struct incfs_file_header { enum incfs_block_map_entry_flags { INCFS_BLOCK_COMPRESSED_LZ4 = (1 << 0), + INCFS_BLOCK_HASH = (1 << 1), }; /* Block map entry pointing to an actual location of the data block. */ @@ -217,27 +222,27 @@ struct incfs_file_attr { __le32 fa_crc; } __packed; -/* Metadata record for file attribute. Type = INCFS_MD_SIGNATURE */ +/* Metadata record for file signature. Type = INCFS_MD_SIGNATURE */ struct incfs_file_signature { struct incfs_md_header sg_header; - __u8 sg_hash_alg; /* Value from incfs_hash_tree_algorithm */ + __le32 sg_sig_size; /* The size of the signature. */ + + __le64 sg_sig_offset; /* Signature's offset in the backing file */ __le32 sg_hash_tree_size; /* The size of the hash tree. */ __le64 sg_hash_tree_offset; /* Hash tree offset in the backing file */ - - __u8 sg_root_hash[INCFS_MAX_HASH_SIZE]; - - __le32 sg_sig_size; /* The size of the pkcs7 signature. */ - - __le64 sg_sig_offset; /* pkcs7 signature's offset in the backing file */ - - __le32 sg_add_data_size; /* The size of the additional data. */ - - __le64 sg_add_data_offset; /* Additional data's offset */ } __packed; +/* In memory version of above */ +struct incfs_df_signature { + u32 sig_size; + u64 sig_offset; + u32 hash_size; + u64 hash_offset; +}; + /* State of the backing file. */ struct backing_file_context { /* Protects writes to bc_file */ @@ -253,23 +258,6 @@ struct backing_file_context { loff_t bc_last_md_record_offset; }; - -/* Backing file locations of things required for signature validation. */ -struct ondisk_signature { - - loff_t add_data_offset; /* Additional data's offset */ - - loff_t sig_offset; /* pkcs7 signature's offset in the backing file */ - - loff_t mtree_offset; /* Backing file offset of the hash tree. */ - - u32 add_data_size; /* The size of the additional data. */ - - u32 sig_size; /* The size of the pkcs7 signature. */ - - u32 mtree_size; /* The size of the hash tree. */ -}; - struct metadata_handler { loff_t md_record_offset; loff_t md_prev_record_offset; @@ -301,7 +289,7 @@ void incfs_free_bfc(struct backing_file_context *bfc); /* Writing stuff */ int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc, - u32 block_count, loff_t *map_base_off); + u32 block_count); int incfs_write_fh_to_backing_file(struct backing_file_context *bfc, incfs_uuid_t *uuid, u64 file_size); @@ -312,16 +300,18 @@ int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc, u16 flags); int incfs_write_hash_block_to_backing_file(struct backing_file_context *bfc, - struct mem_range block, - int block_index, loff_t hash_area_off); + struct mem_range block, + int block_index, + loff_t hash_area_off, + loff_t bm_base_off, int file_size); int incfs_write_file_attr_to_backing_file(struct backing_file_context *bfc, struct mem_range value, struct incfs_file_attr *attr); int incfs_write_signature_to_backing_file(struct backing_file_context *bfc, - u8 hash_alg, u32 tree_size, - struct mem_range root_hash, struct mem_range add_data, - struct mem_range sig); + struct mem_range sig, u32 tree_size); + +int incfs_update_file_header_flags(struct backing_file_context *bfc, u32 flags); int incfs_make_empty_backing_file(struct backing_file_context *bfc, incfs_uuid_t *uuid, u64 file_size); @@ -329,7 +319,7 @@ int incfs_make_empty_backing_file(struct backing_file_context *bfc, /* Reading stuff */ int incfs_read_file_header(struct backing_file_context *bfc, loff_t *first_md_off, incfs_uuid_t *uuid, - u64 *file_size); + u64 *file_size, u32 *flags); int incfs_read_blockmap_entry(struct backing_file_context *bfc, int block_index, loff_t bm_base_off, diff --git a/fs/incfs/integrity.c b/fs/incfs/integrity.c index feb212c38945..96e016a91542 100644 --- a/fs/incfs/integrity.c +++ b/fs/incfs/integrity.c @@ -10,70 +10,6 @@ #include "integrity.h" -int incfs_validate_pkcs7_signature(struct mem_range pkcs7_blob, - struct mem_range root_hash, struct mem_range add_data) -{ - struct pkcs7_message *pkcs7 = NULL; - const void *data = NULL; - size_t data_len = 0; - const char *p; - int err; - - pkcs7 = pkcs7_parse_message(pkcs7_blob.data, pkcs7_blob.len); - if (IS_ERR(pkcs7)) { - pr_debug("PKCS#7 parsing error. ptr=%p size=%ld err=%ld\n", - pkcs7_blob.data, pkcs7_blob.len, -PTR_ERR(pkcs7)); - return PTR_ERR(pkcs7); - } - - err = pkcs7_get_content_data(pkcs7, &data, &data_len, NULL); - if (err || data_len == 0 || data == NULL) { - pr_debug("PKCS#7 message does not contain data\n"); - err = -EBADMSG; - goto out; - } - - if (root_hash.len == 0) { - pr_debug("Root hash is empty.\n"); - err = -EBADMSG; - goto out; - } - - if (data_len != root_hash.len + add_data.len) { - pr_debug("PKCS#7 data size doesn't match arguments.\n"); - err = -EKEYREJECTED; - goto out; - } - - p = data; - if (memcmp(p, root_hash.data, root_hash.len) != 0) { - pr_debug("Root hash mismatch.\n"); - err = -EKEYREJECTED; - goto out; - } - p += root_hash.len; - if (memcmp(p, add_data.data, add_data.len) != 0) { - pr_debug("Additional data mismatch.\n"); - err = -EKEYREJECTED; - goto out; - } - - err = pkcs7_verify(pkcs7, VERIFYING_UNSPECIFIED_SIGNATURE); - if (err) - pr_debug("PKCS#7 signature verification error: %d\n", -err); - - /* - * RSA signature verification sometimes returns unexpected error codes - * when signature doesn't match. - */ - if (err == -ERANGE || err == -EINVAL) - err = -EBADMSG; - -out: - pkcs7_free_message(pkcs7); - return err; -} - struct incfs_hash_alg *incfs_get_hash_alg(enum incfs_hash_tree_algorithm id) { static struct incfs_hash_alg sha256 = { @@ -113,11 +49,90 @@ struct incfs_hash_alg *incfs_get_hash_alg(enum incfs_hash_tree_algorithm id) return result; } +struct signature_info { + u32 version; + enum incfs_hash_tree_algorithm hash_algorithm; + u8 log2_blocksize; + struct mem_range salt; + struct mem_range root_hash; +}; -struct mtree *incfs_alloc_mtree(enum incfs_hash_tree_algorithm id, - int data_block_count, - struct mem_range root_hash) +static bool read_u32(u8 **p, u8 *top, u32 *result) { + if (*p + sizeof(u32) > top) + return false; + + *result = le32_to_cpu(*(u32 *)*p); + *p += sizeof(u32); + return true; +} + +static bool read_u8(u8 **p, u8 *top, u8 *result) +{ + if (*p + sizeof(u8) > top) + return false; + + *result = *(u8 *)*p; + *p += sizeof(u8); + return true; +} + +static bool read_mem_range(u8 **p, u8 *top, struct mem_range *range) +{ + u32 len; + + if (!read_u32(p, top, &len) || *p + len > top) + return false; + + range->len = len; + range->data = *p; + *p += len; + return true; +} + +static int incfs_parse_signature(struct mem_range signature, + struct signature_info *si) +{ + u8 *p = signature.data; + u8 *top = signature.data + signature.len; + u32 hash_section_size; + + if (signature.len > INCFS_MAX_SIGNATURE_SIZE) + return -EINVAL; + + if (!read_u32(&p, top, &si->version) || + si->version != INCFS_SIGNATURE_VERSION) + return -EINVAL; + + if (!read_u32(&p, top, &hash_section_size) || + p + hash_section_size > top) + return -EINVAL; + top = p + hash_section_size; + + if (!read_u32(&p, top, &si->hash_algorithm) || + si->hash_algorithm != INCFS_HASH_TREE_SHA256) + return -EINVAL; + + if (!read_u8(&p, top, &si->log2_blocksize) || si->log2_blocksize != 12) + return -EINVAL; + + if (!read_mem_range(&p, top, &si->salt)) + return -EINVAL; + + if (!read_mem_range(&p, top, &si->root_hash)) + return -EINVAL; + + if (p != top) + return -EINVAL; + + return 0; +} + +struct mtree *incfs_alloc_mtree(struct mem_range signature, + int data_block_count) +{ + int error; + struct signature_info si; struct mtree *result = NULL; struct incfs_hash_alg *hash_alg = NULL; int hash_per_block; @@ -129,11 +144,15 @@ struct mtree *incfs_alloc_mtree(enum incfs_hash_tree_algorithm id, if (data_block_count <= 0) return ERR_PTR(-EINVAL); - hash_alg = incfs_get_hash_alg(id); + error = incfs_parse_signature(signature, &si); + if (error) + return ERR_PTR(error); + + hash_alg = incfs_get_hash_alg(si.hash_algorithm); if (IS_ERR(hash_alg)) return ERR_PTR(PTR_ERR(hash_alg)); - if (root_hash.len < hash_alg->digest_size) + if (si.root_hash.len < hash_alg->digest_size) return ERR_PTR(-EINVAL); result = kzalloc(sizeof(*result), GFP_NOFS); @@ -173,7 +192,7 @@ struct mtree *incfs_alloc_mtree(enum incfs_hash_tree_algorithm id, } /* Root hash is stored separately from the rest of the tree. */ - memcpy(result->root_hash, root_hash.data, hash_alg->digest_size); + memcpy(result->root_hash, si.root_hash.data, hash_alg->digest_size); return result; err: @@ -198,16 +217,20 @@ int incfs_calc_digest(struct incfs_hash_alg *alg, struct mem_range data, return -EINVAL; desc->tfm = alg->shash; + + if (data.len < INCFS_DATA_FILE_BLOCK_SIZE) { + int err; + void *buf = kzalloc(INCFS_DATA_FILE_BLOCK_SIZE, GFP_NOFS); + + if (!buf) + return -ENOMEM; + + memcpy(buf, data.data, data.len); + err = crypto_shash_digest(desc, buf, INCFS_DATA_FILE_BLOCK_SIZE, + digest.data); + kfree(buf); + return err; + } return crypto_shash_digest(desc, data.data, data.len, digest.data); } -void incfs_free_signature_info(struct signature_info *si) -{ - if (!si) - return; - kfree(si->root_hash.data); - kfree(si->additional_data.data); - kfree(si->signature.data); - kfree(si); -} - diff --git a/fs/incfs/integrity.h b/fs/incfs/integrity.h index da1c38486b2f..cf79b64da736 100644 --- a/fs/incfs/integrity.h +++ b/fs/incfs/integrity.h @@ -38,21 +38,10 @@ struct mtree { int depth; }; -struct signature_info { - struct mem_range root_hash; - - struct mem_range additional_data; - - struct mem_range signature; - - enum incfs_hash_tree_algorithm hash_alg; -}; - struct incfs_hash_alg *incfs_get_hash_alg(enum incfs_hash_tree_algorithm id); -struct mtree *incfs_alloc_mtree(enum incfs_hash_tree_algorithm id, - int data_block_count, - struct mem_range root_hash); +struct mtree *incfs_alloc_mtree(struct mem_range signature, + int data_block_count); void incfs_free_mtree(struct mtree *tree); @@ -64,9 +53,4 @@ size_t incfs_get_mtree_hash_count(enum incfs_hash_tree_algorithm alg, int incfs_calc_digest(struct incfs_hash_alg *alg, struct mem_range data, struct mem_range digest); -int incfs_validate_pkcs7_signature(struct mem_range pkcs7_blob, - struct mem_range root_hash, struct mem_range add_data); - -void incfs_free_signature_info(struct signature_info *si); - #endif /* _INCFS_INTEGRITY_H */ diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index f30ede3fa84d..ffa5b7ef9d5e 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -49,8 +49,6 @@ static int dir_rename(struct inode *old_dir, struct dentry *old_dentry, static int file_open(struct inode *inode, struct file *file); static int file_release(struct inode *inode, struct file *file); -static ssize_t file_write(struct file *f, const char __user *buf, - size_t size, loff_t *offset); static int read_single_page(struct file *f, struct page *page); static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg); @@ -126,7 +124,6 @@ static const struct address_space_operations incfs_address_space_ops = { static const struct file_operations incfs_file_ops = { .open = file_open, .release = file_release, - .write = file_write, .read_iter = generic_file_read_iter, .mmap = generic_file_mmap, .splice_read = generic_file_splice_read, @@ -135,6 +132,11 @@ static const struct file_operations incfs_file_ops = { .compat_ioctl = dispatch_ioctl }; +enum FILL_PERMISSION { + CANT_FILL = 0, + CAN_FILL = 1, +}; + static const struct file_operations incfs_pending_read_file_ops = { .read = pending_reads_read, .poll = pending_reads_poll, @@ -463,9 +465,6 @@ static ssize_t pending_reads_read(struct file *f, char __user *buf, size_t len, ssize_t result = 0; int i = 0; - if (!access_ok(buf, len)) - return -EFAULT; - if (!incfs_fresh_pending_reads_exist(mi, last_known_read_sn)) return 0; @@ -798,9 +797,6 @@ static int read_single_page(struct file *f, struct page *page) size = df->df_size; timeout_ms = df->df_mount_info->mi_options.read_timeout_ms; - pr_debug("incfs: %s %s %lld\n", __func__, - f->f_path.dentry->d_name.name, offset); - if (offset < size) { struct mem_range tmp = { .len = 2 * INCFS_DATA_FILE_BLOCK_SIZE @@ -847,107 +843,39 @@ static char *file_id_to_str(incfs_uuid_t id) return result; } -static struct signature_info *incfs_copy_signature_info_from_user( - struct incfs_file_signature_info __user *original) +static struct mem_range incfs_copy_signature_info_from_user(u8 __user *original, + u64 size) { - struct incfs_file_signature_info usr_si; - struct signature_info *result; - int error; + u8 *result; if (!original) - return NULL; + return range(NULL, 0); - if (!access_ok(original, sizeof(usr_si))) - return ERR_PTR(-EFAULT); + if (size > INCFS_MAX_SIGNATURE_SIZE) + return range(ERR_PTR(-EFAULT), 0); - if (copy_from_user(&usr_si, original, sizeof(usr_si)) > 0) - return ERR_PTR(-EFAULT); - - result = kzalloc(sizeof(*result), GFP_NOFS); + result = kzalloc(size, GFP_NOFS); if (!result) - return ERR_PTR(-ENOMEM); + return range(ERR_PTR(-ENOMEM), 0); - result->hash_alg = usr_si.hash_tree_alg; - - if (result->hash_alg) { - void *p = kzalloc(INCFS_MAX_HASH_SIZE, GFP_NOFS); - - if (!p) { - error = -ENOMEM; - goto err; - } - - /* TODO this sets the root_hash length to MAX_HASH_SIZE not - * the actual size. Fix, then set INCFS_MAX_HASH_SIZE back - * to 64 - */ - result->root_hash = range(p, INCFS_MAX_HASH_SIZE); - if (copy_from_user(p, u64_to_user_ptr(usr_si.root_hash), - result->root_hash.len) > 0) { - error = -EFAULT; - goto err; - } + if (copy_from_user(result, original, size)) { + kfree(result); + return range(ERR_PTR(-EFAULT), 0); } - if (usr_si.additional_data_size > INCFS_MAX_FILE_ATTR_SIZE) { - error = -E2BIG; - goto err; - } - - if (usr_si.additional_data && usr_si.additional_data_size) { - void *p = kzalloc(usr_si.additional_data_size, GFP_NOFS); - - if (!p) { - error = -ENOMEM; - goto err; - } - result->additional_data = range(p, - usr_si.additional_data_size); - if (copy_from_user(p, u64_to_user_ptr(usr_si.additional_data), - result->additional_data.len) > 0) { - error = -EFAULT; - goto err; - } - } - - if (usr_si.signature_size > INCFS_MAX_SIGNATURE_SIZE) { - error = -E2BIG; - goto err; - } - - if (usr_si.signature && usr_si.signature_size) { - void *p = kzalloc(usr_si.signature_size, GFP_NOFS); - - if (!p) { - error = -ENOMEM; - goto err; - } - result->signature = range(p, usr_si.signature_size); - if (copy_from_user(p, u64_to_user_ptr(usr_si.signature), - result->signature.len) > 0) { - error = -EFAULT; - goto err; - } - } - - return result; - -err: - incfs_free_signature_info(result); - return ERR_PTR(-error); + return range(result, size); } static int init_new_file(struct mount_info *mi, struct dentry *dentry, - incfs_uuid_t *uuid, u64 size, struct mem_range attr, - struct incfs_file_signature_info __user *fsi) + incfs_uuid_t *uuid, u64 size, struct mem_range attr, + u8 __user *user_signature_info, u64 signature_size) { struct path path = {}; struct file *new_file; int error = 0; struct backing_file_context *bfc = NULL; u32 block_count; - struct mem_range mem_range = {NULL}; - struct signature_info *si = NULL; + struct mem_range raw_signature = { NULL }; struct mtree *hash_tree = NULL; if (!mi || !dentry || !uuid) @@ -977,19 +905,6 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, if (error) goto out; - block_count = (u32)get_blocks_count_for_size(size); - error = incfs_write_blockmap_to_backing_file(bfc, block_count, NULL); - if (error) - goto out; - - /* This fill has data, reserve space for the block map. */ - if (block_count > 0) { - error = incfs_write_blockmap_to_backing_file( - bfc, block_count, NULL); - if (error) - goto out; - } - if (attr.data && attr.len) { error = incfs_write_file_attr_to_backing_file(bfc, attr, NULL); @@ -997,54 +912,46 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, goto out; } - if (fsi) { - si = incfs_copy_signature_info_from_user(fsi); + block_count = (u32)get_blocks_count_for_size(size); - if (IS_ERR(si)) { - error = PTR_ERR(si); - si = NULL; + if (user_signature_info) { + raw_signature = incfs_copy_signature_info_from_user( + user_signature_info, signature_size); + + if (IS_ERR(raw_signature.data)) { + error = PTR_ERR(raw_signature.data); + raw_signature.data = NULL; goto out; } - if (si->hash_alg) { - hash_tree = incfs_alloc_mtree(si->hash_alg, block_count, - si->root_hash); - if (IS_ERR(hash_tree)) { - error = PTR_ERR(hash_tree); - hash_tree = NULL; - goto out; - } - - /* TODO This code seems wrong when len is zero - we - * should error out?? - */ - if (si->signature.len > 0) - error = incfs_validate_pkcs7_signature( - si->signature, - si->root_hash, - si->additional_data); - if (error) - goto out; - - error = incfs_write_signature_to_backing_file(bfc, - si->hash_alg, - hash_tree->hash_tree_area_size, - si->root_hash, si->additional_data, - si->signature); - - if (error) - goto out; + hash_tree = incfs_alloc_mtree(raw_signature, block_count); + if (IS_ERR(hash_tree)) { + error = PTR_ERR(hash_tree); + hash_tree = NULL; + goto out; } + + error = incfs_write_signature_to_backing_file( + bfc, raw_signature, hash_tree->hash_tree_area_size); + if (error) + goto out; + + block_count += get_blocks_count_for_size( + hash_tree->hash_tree_area_size); } + if (block_count) + error = incfs_write_blockmap_to_backing_file(bfc, block_count); + + if (error) + goto out; out: if (bfc) { mutex_unlock(&bfc->bc_mutex); incfs_free_bfc(bfc); } incfs_free_mtree(hash_tree); - incfs_free_signature_info(si); - kfree(mem_range.data); + kfree(raw_signature.data); if (error) pr_debug("incfs: %s error: %d\n", __func__, error); @@ -1189,10 +1096,7 @@ static long ioctl_create_file(struct mount_info *mi, error = -EFAULT; goto out; } - if (!access_ok(usr_args, sizeof(args))) { - error = -EFAULT; - goto out; - } + if (copy_from_user(&args, usr_args, sizeof(args)) > 0) { error = -EFAULT; goto out; @@ -1305,7 +1209,7 @@ static long ioctl_create_file(struct mount_info *mi, goto delete_index_file; } - /* Save the file's attrubute as an xattr */ + /* Save the file's attribute as an xattr */ if (args.file_attr_len && args.file_attr) { if (args.file_attr_len > INCFS_MAX_FILE_ATTR_SIZE) { error = -E2BIG; @@ -1318,12 +1222,6 @@ static long ioctl_create_file(struct mount_info *mi, goto delete_index_file; } - if (!access_ok(u64_to_user_ptr(args.file_attr), - args.file_attr_len)) { - error = -EFAULT; - goto delete_index_file; - } - if (copy_from_user(attr_value, u64_to_user_ptr(args.file_attr), args.file_attr_len) > 0) { @@ -1342,9 +1240,9 @@ static long ioctl_create_file(struct mount_info *mi, /* Initializing a newly created file. */ error = init_new_file(mi, index_file_dentry, &args.file_id, args.size, - range(attr_value, args.file_attr_len), - (struct incfs_file_signature_info __user *) - args.signature_info); + range(attr_value, args.file_attr_len), + (u8 __user *)args.signature_info, + args.signature_size); if (error) goto delete_index_file; @@ -1372,6 +1270,122 @@ out: return error; } +static long ioctl_fill_blocks(struct file *f, void __user *arg) +{ + struct incfs_fill_blocks __user *usr_fill_blocks = arg; + struct incfs_fill_blocks fill_blocks; + struct incfs_fill_block *usr_fill_block_array; + struct data_file *df = get_incfs_data_file(f); + const ssize_t data_buf_size = 2 * INCFS_DATA_FILE_BLOCK_SIZE; + u8 *data_buf = NULL; + ssize_t error = 0; + int i = 0; + + if (!df) + return -EBADF; + + if ((uintptr_t)f->private_data != CAN_FILL) + return -EPERM; + + if (copy_from_user(&fill_blocks, usr_fill_blocks, sizeof(fill_blocks))) + return -EFAULT; + + usr_fill_block_array = u64_to_user_ptr(fill_blocks.fill_blocks); + data_buf = (u8 *)__get_free_pages(GFP_NOFS, get_order(data_buf_size)); + if (!data_buf) + return -ENOMEM; + + for (i = 0; i < fill_blocks.count; i++) { + struct incfs_fill_block fill_block = {}; + + if (copy_from_user(&fill_block, &usr_fill_block_array[i], + sizeof(fill_block)) > 0) { + error = -EFAULT; + break; + } + + if (fill_block.data_len > data_buf_size) { + error = -E2BIG; + break; + } + + if (copy_from_user(data_buf, u64_to_user_ptr(fill_block.data), + fill_block.data_len) > 0) { + error = -EFAULT; + break; + } + fill_block.data = 0; /* To make sure nobody uses it. */ + if (fill_block.flags & INCFS_BLOCK_FLAGS_HASH) { + error = incfs_process_new_hash_block(df, &fill_block, + data_buf); + } else { + error = incfs_process_new_data_block(df, &fill_block, + data_buf); + } + if (error) + break; + } + + if (data_buf) + free_pages((unsigned long)data_buf, get_order(data_buf_size)); + + /* + * Only report the error if no records were processed, otherwise + * just return how many were processed successfully. + */ + if (i == 0) + return error; + + return i; +} + +static long ioctl_permit_fill(struct file *f, void __user *arg) +{ + struct incfs_permit_fill __user *usr_permit_fill = arg; + struct incfs_permit_fill permit_fill; + long error = 0; + struct file *file = 0; + + if (f->f_op != &incfs_pending_read_file_ops) + return -EPERM; + + if (copy_from_user(&permit_fill, usr_permit_fill, sizeof(permit_fill))) + return -EFAULT; + + file = fget(permit_fill.file_descriptor); + if (IS_ERR(file)) + return PTR_ERR(file); + + if (file->f_op != &incfs_file_ops) { + error = -EPERM; + goto out; + } + + if (file->f_inode->i_sb != f->f_inode->i_sb) { + error = -EPERM; + goto out; + } + + switch ((uintptr_t)file->private_data) { + case CANT_FILL: + file->private_data = (void *)CAN_FILL; + break; + + case CAN_FILL: + pr_debug("CAN_FILL already set"); + break; + + default: + pr_warn("Invalid file private data"); + error = -EFAULT; + goto out; + } + +out: + fput(file); + return error; +} + static long ioctl_read_file_signature(struct file *f, void __user *arg) { struct incfs_get_file_sig_args __user *args_usr_ptr = arg; @@ -1385,15 +1399,9 @@ static long ioctl_read_file_signature(struct file *f, void __user *arg) if (!df) return -EINVAL; - if (!access_ok(args_usr_ptr, sizeof(args))) - return -EFAULT; if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0) return -EINVAL; - if (!access_ok(u64_to_user_ptr(args.file_signature), - args.file_signature_buf_size)) - return -EFAULT; - sig_buf_size = args.file_signature_buf_size; if (sig_buf_size > INCFS_MAX_SIGNATURE_SIZE) return -E2BIG; @@ -1426,6 +1434,27 @@ out: return error; } +static long ioctl_get_filled_blocks(struct file *f, void __user *arg) +{ + struct incfs_get_filled_blocks_args __user *args_usr_ptr = arg; + struct incfs_get_filled_blocks_args args = {}; + struct data_file *df = get_incfs_data_file(f); + int error; + + if (!df) + return -EINVAL; + + if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0) + return -EINVAL; + + error = incfs_get_filled_blocks(df, &args); + + if (copy_to_user(args_usr_ptr, &args, sizeof(args))) + return -EFAULT; + + return error; +} + static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg) { struct mount_info *mi = get_mount_info(file_superblock(f)); @@ -1433,8 +1462,14 @@ static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg) switch (req) { case INCFS_IOC_CREATE_FILE: return ioctl_create_file(mi, (void __user *)arg); + case INCFS_IOC_FILL_BLOCKS: + return ioctl_fill_blocks(f, (void __user *)arg); + case INCFS_IOC_PERMIT_FILL: + return ioctl_permit_fill(f, (void __user *)arg); case INCFS_IOC_READ_FILE_SIGNATURE: return ioctl_read_file_signature(f, (void __user *)arg); + case INCFS_IOC_GET_FILLED_BLOCKS: + return ioctl_get_filled_blocks(f, (void __user *)arg); default: return -EINVAL; } @@ -1863,9 +1898,10 @@ static int file_open(struct inode *inode, struct file *file) goto out; } - if (S_ISREG(inode->i_mode)) + if (S_ISREG(inode->i_mode)) { err = make_inode_ready_for_data_ops(mi, inode, backing_file); - else if (S_ISDIR(inode->i_mode)) { + file->private_data = (void *)CANT_FILL; + } else if (S_ISDIR(inode->i_mode)) { struct dir_file *dir = NULL; dir = incfs_open_dir_file(mi, backing_file); @@ -1900,77 +1936,6 @@ static int file_release(struct inode *inode, struct file *file) return 0; } -static ssize_t file_write(struct file *f, const char __user *buf, - size_t size, loff_t *offset) -{ - struct data_file *df = get_incfs_data_file(f); - const ssize_t data_buf_size = 2 * INCFS_DATA_FILE_BLOCK_SIZE; - size_t block_count = size / sizeof(struct incfs_new_data_block); - struct incfs_new_data_block __user *usr_blocks = - (struct incfs_new_data_block __user *)buf; - u8 *data_buf = NULL; - ssize_t error = 0; - int i = 0; - - if (!df) - return -EBADF; - - if (!access_ok(usr_blocks, size)) - return -EFAULT; - - data_buf = (u8 *)__get_free_pages(GFP_NOFS, get_order(data_buf_size)); - if (!data_buf) - return -ENOMEM; - - for (i = 0; i < block_count; i++) { - struct incfs_new_data_block block = {}; - - if (copy_from_user(&block, &usr_blocks[i], sizeof(block)) > 0) { - error = -EFAULT; - break; - } - - if (block.data_len > data_buf_size) { - error = -E2BIG; - break; - } - if (!access_ok(u64_to_user_ptr(block.data), - block.data_len)) { - error = -EFAULT; - break; - } - if (copy_from_user(data_buf, u64_to_user_ptr(block.data), - block.data_len) > 0) { - error = -EFAULT; - break; - } - block.data = 0; /* To make sure nobody uses it. */ - if (block.flags & INCFS_BLOCK_FLAGS_HASH) { - error = incfs_process_new_hash_block(df, &block, - data_buf); - } else { - error = incfs_process_new_data_block(df, &block, - data_buf); - } - if (error) - break; - } - - if (data_buf) - free_pages((unsigned long)data_buf, get_order(data_buf_size)); - *offset = 0; - - /* - * Only report the error if no records were processed, otherwise - * just return how many were processed successfully. - */ - if (i == 0) - return error; - - return i * sizeof(struct incfs_new_data_block); -} - - static int dentry_revalidate(struct dentry *d, unsigned int flags) { struct path backing_path = {}; diff --git a/fs/inode.c b/fs/inode.c index 8877c427c00e..64d502af7549 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -138,6 +138,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_sb = sb; inode->i_blkbits = sb->s_blocksize_bits; inode->i_flags = 0; + atomic64_set(&inode->i_sequence, 0); atomic_set(&inode->i_count, 1); inode->i_op = &empty_iops; inode->i_fop = &no_open_fops; diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index b17f05ae6011..de992a70ddfe 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1079,8 +1079,8 @@ static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh, /* For undo access buffer must have data copied */ if (undo && !jh->b_committed_data) goto out; - if (jh->b_transaction != handle->h_transaction && - jh->b_next_transaction != handle->h_transaction) + if (READ_ONCE(jh->b_transaction) != handle->h_transaction && + READ_ONCE(jh->b_next_transaction) != handle->h_transaction) goto out; /* * There are two reasons for the barrier here: @@ -2535,8 +2535,8 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh) * our jh reference and thus __jbd2_journal_file_buffer() must not * take a new one. */ - jh->b_transaction = jh->b_next_transaction; - jh->b_next_transaction = NULL; + WRITE_ONCE(jh->b_transaction, jh->b_next_transaction); + WRITE_ONCE(jh->b_next_transaction, NULL); if (buffer_freed(bh)) jlist = BJ_Forget; else if (jh->b_modified) diff --git a/fs/libfs.c b/fs/libfs.c index a799550cdbab..017fe0b843f0 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -823,7 +823,7 @@ int simple_attr_open(struct inode *inode, struct file *file, { struct simple_attr *attr; - attr = kmalloc(sizeof(*attr), GFP_KERNEL); + attr = kzalloc(sizeof(*attr), GFP_KERNEL); if (!attr) return -ENOMEM; @@ -863,9 +863,11 @@ ssize_t simple_attr_read(struct file *file, char __user *buf, if (ret) return ret; - if (*ppos) { /* continued read */ + if (*ppos && attr->get_buf[0]) { + /* continued read */ size = strlen(attr->get_buf); - } else { /* first read */ + } else { + /* first read */ u64 val; ret = attr->get(attr->data, &val); if (ret) diff --git a/fs/locks.c b/fs/locks.c index 44b6da032842..b8a31c1c4fff 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -725,7 +725,6 @@ static void __locks_delete_block(struct file_lock *waiter) { locks_delete_global_blocked(waiter); list_del_init(&waiter->fl_blocked_member); - waiter->fl_blocker = NULL; } static void __locks_wake_up_blocks(struct file_lock *blocker) @@ -740,6 +739,13 @@ static void __locks_wake_up_blocks(struct file_lock *blocker) waiter->fl_lmops->lm_notify(waiter); else wake_up(&waiter->fl_wait); + + /* + * The setting of fl_blocker to NULL marks the "done" + * point in deleting a block. Paired with acquire at the top + * of locks_delete_block(). + */ + smp_store_release(&waiter->fl_blocker, NULL); } } @@ -754,24 +760,41 @@ int locks_delete_block(struct file_lock *waiter) int status = -ENOENT; /* - * If fl_blocker is NULL, it won't be set again as this thread - * "owns" the lock and is the only one that might try to claim - * the lock. So it is safe to test fl_blocker locklessly. - * Also if fl_blocker is NULL, this waiter is not listed on - * fl_blocked_requests for some lock, so no other request can - * be added to the list of fl_blocked_requests for this - * request. So if fl_blocker is NULL, it is safe to - * locklessly check if fl_blocked_requests is empty. If both - * of these checks succeed, there is no need to take the lock. + * If fl_blocker is NULL, it won't be set again as this thread "owns" + * the lock and is the only one that might try to claim the lock. + * + * We use acquire/release to manage fl_blocker so that we can + * optimize away taking the blocked_lock_lock in many cases. + * + * The smp_load_acquire guarantees two things: + * + * 1/ that fl_blocked_requests can be tested locklessly. If something + * was recently added to that list it must have been in a locked region + * *before* the locked region when fl_blocker was set to NULL. + * + * 2/ that no other thread is accessing 'waiter', so it is safe to free + * it. __locks_wake_up_blocks is careful not to touch waiter after + * fl_blocker is released. + * + * If a lockless check of fl_blocker shows it to be NULL, we know that + * no new locks can be inserted into its fl_blocked_requests list, and + * can avoid doing anything further if the list is empty. */ - if (waiter->fl_blocker == NULL && + if (!smp_load_acquire(&waiter->fl_blocker) && list_empty(&waiter->fl_blocked_requests)) return status; + spin_lock(&blocked_lock_lock); if (waiter->fl_blocker) status = 0; __locks_wake_up_blocks(waiter); __locks_delete_block(waiter); + + /* + * The setting of fl_blocker to NULL marks the "done" point in deleting + * a block. Paired with acquire at the top of this function. + */ + smp_store_release(&waiter->fl_blocker, NULL); spin_unlock(&blocked_lock_lock); return status; } @@ -1364,7 +1387,8 @@ static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl) error = posix_lock_inode(inode, fl, NULL); if (error != FILE_LOCK_DEFERRED) break; - error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); + error = wait_event_interruptible(fl->fl_wait, + list_empty(&fl->fl_blocked_member)); if (error) break; } @@ -1449,7 +1473,8 @@ int locks_mandatory_area(struct inode *inode, struct file *filp, loff_t start, error = posix_lock_inode(inode, &fl, NULL); if (error != FILE_LOCK_DEFERRED) break; - error = wait_event_interruptible(fl.fl_wait, !fl.fl_blocker); + error = wait_event_interruptible(fl.fl_wait, + list_empty(&fl.fl_blocked_member)); if (!error) { /* * If we've been sleeping someone might have @@ -1652,7 +1677,8 @@ restart: locks_dispose_list(&dispose); error = wait_event_interruptible_timeout(new_fl->fl_wait, - !new_fl->fl_blocker, break_time); + list_empty(&new_fl->fl_blocked_member), + break_time); percpu_down_read(&file_rwsem); spin_lock(&ctx->flc_lock); @@ -2136,7 +2162,8 @@ static int flock_lock_inode_wait(struct inode *inode, struct file_lock *fl) error = flock_lock_inode(inode, fl); if (error != FILE_LOCK_DEFERRED) break; - error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); + error = wait_event_interruptible(fl->fl_wait, + list_empty(&fl->fl_blocked_member)); if (error) break; } @@ -2413,7 +2440,8 @@ static int do_lock_file_wait(struct file *filp, unsigned int cmd, error = vfs_lock_file(filp, cmd, fl, NULL); if (error != FILE_LOCK_DEFERRED) break; - error = wait_event_interruptible(fl->fl_wait, !fl->fl_blocker); + error = wait_event_interruptible(fl->fl_wait, + list_empty(&fl->fl_blocked_member)); if (error) break; } diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 30838304a0bf..a05f77f9c21e 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -153,6 +153,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) goto error_0; + clp->cl_minorversion = cl_init->minorversion; clp->cl_nfs_mod = cl_init->nfs_mod; if (!try_module_get(clp->cl_nfs_mod->owner)) goto error_dealloc; diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index 3800ab6f08fa..a6dcc2151e77 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -31,6 +31,7 @@ static DEFINE_SPINLOCK(nfs_fscache_keys_lock); struct nfs_server_key { struct { uint16_t nfsversion; /* NFS protocol version */ + uint32_t minorversion; /* NFSv4 minor version */ uint16_t family; /* address family */ __be16 port; /* IP port */ } hdr; @@ -55,6 +56,7 @@ void nfs_fscache_get_client_cookie(struct nfs_client *clp) memset(&key, 0, sizeof(key)); key.hdr.nfsversion = clp->rpc_ops->version; + key.hdr.minorversion = clp->cl_minorversion; key.hdr.family = clp->cl_addr.ss_family; switch (clp->cl_addr.ss_family) { diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index da6204025a2d..914feab64702 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -216,7 +216,6 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) INIT_LIST_HEAD(&clp->cl_ds_clients); rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; - clp->cl_minorversion = cl_init->minorversion; clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; clp->cl_mig_gen = 1; #if IS_ENABLED(CONFIG_NFS_V4_1) diff --git a/fs/open.c b/fs/open.c index 681affa0cb37..457fac8b01cf 100644 --- a/fs/open.c +++ b/fs/open.c @@ -872,9 +872,6 @@ cleanup_file: * the return value of d_splice_alias(), then the caller needs to perform dput() * on it after finish_open(). * - * On successful return @file is a fully instantiated open file. After this, if - * an error occurs in ->atomic_open(), it needs to clean up with fput(). - * * Returns zero on success or -errno if the open failed. */ int finish_open(struct file *file, struct dentry *dentry, diff --git a/fs/proc/Kconfig b/fs/proc/Kconfig index 313ae27bb674..cb5629bd5fff 100644 --- a/fs/proc/Kconfig +++ b/fs/proc/Kconfig @@ -103,9 +103,3 @@ config PROC_CHILDREN config PROC_PID_ARCH_STATUS def_bool n depends on PROC_FS - -config PROC_UID - bool "Include /proc/uid/ files" - depends on PROC_FS && RT_MUTEXES - help - Provides aggregated per-uid information under /proc/uid. diff --git a/fs/proc/Makefile b/fs/proc/Makefile index 3f849ca0edce..ead487e80510 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile @@ -27,7 +27,6 @@ proc-y += softirqs.o proc-y += namespaces.o proc-y += self.o proc-y += thread_self.o -proc-$(CONFIG_PROC_UID) += uid.o proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o proc-$(CONFIG_NET) += proc_net.o proc-$(CONFIG_PROC_KCORE) += kcore.o diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 95846552ef24..cd0c8d5ce9a1 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -253,15 +253,6 @@ static inline void proc_sys_evict_inode(struct inode *inode, struct ctl_table_header *head) { } #endif -/* - * uid.c - */ -#ifdef CONFIG_PROC_UID -extern int proc_uid_init(void); -#else -static inline void proc_uid_init(void) { } -#endif - /* * proc_tty.c */ diff --git a/fs/proc/root.c b/fs/proc/root.c index e277722f443b..44f78d3db983 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -221,7 +221,6 @@ void __init proc_root_init(void) proc_symlink("mounts", NULL, "self/mounts"); proc_net_init(); - proc_uid_init(); proc_mkdir("fs", NULL); proc_mkdir("driver", NULL); proc_create_mount_point("fs/nfsd"); /* somewhere for the nfsd filesystem to be mounted */ diff --git a/fs/proc/uid.c b/fs/proc/uid.c deleted file mode 100644 index 311717ea199a..000000000000 --- a/fs/proc/uid.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * /proc/uid support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "internal.h" - -static struct proc_dir_entry *proc_uid; - -#define UID_HASH_BITS 10 - -static DECLARE_HASHTABLE(proc_uid_hash_table, UID_HASH_BITS); - -/* - * use rt_mutex here to avoid priority inversion between high-priority readers - * of these files and tasks calling proc_register_uid(). - */ -static DEFINE_RT_MUTEX(proc_uid_lock); /* proc_uid_hash_table */ - -struct uid_hash_entry { - uid_t uid; - struct hlist_node hash; -}; - -/* Caller must hold proc_uid_lock */ -static bool uid_hash_entry_exists_locked(uid_t uid) -{ - struct uid_hash_entry *entry; - - hash_for_each_possible(proc_uid_hash_table, entry, hash, uid) { - if (entry->uid == uid) - return true; - } - return false; -} - -void proc_register_uid(kuid_t kuid) -{ - struct uid_hash_entry *entry; - bool exists; - uid_t uid = from_kuid_munged(current_user_ns(), kuid); - - rt_mutex_lock(&proc_uid_lock); - exists = uid_hash_entry_exists_locked(uid); - rt_mutex_unlock(&proc_uid_lock); - if (exists) - return; - - entry = kzalloc(sizeof(struct uid_hash_entry), GFP_KERNEL); - if (!entry) - return; - entry->uid = uid; - - rt_mutex_lock(&proc_uid_lock); - if (uid_hash_entry_exists_locked(uid)) - kfree(entry); - else - hash_add(proc_uid_hash_table, &entry->hash, uid); - rt_mutex_unlock(&proc_uid_lock); -} - -struct uid_entry { - const char *name; - int len; - umode_t mode; - const struct inode_operations *iop; - const struct file_operations *fop; -}; - -#define NOD(NAME, MODE, IOP, FOP) { \ - .name = (NAME), \ - .len = sizeof(NAME) - 1, \ - .mode = MODE, \ - .iop = IOP, \ - .fop = FOP, \ -} - -#ifdef CONFIG_CPU_FREQ_TIMES -static const struct file_operations proc_uid_time_in_state_operations = { - .open = single_uid_time_in_state_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -static const struct uid_entry uid_base_stuff[] = { -#ifdef CONFIG_CPU_FREQ_TIMES - NOD("time_in_state", 0444, NULL, &proc_uid_time_in_state_operations), -#endif -}; - -static const struct inode_operations proc_uid_def_inode_operations = { - .setattr = proc_setattr, -}; - -static struct inode *proc_uid_make_inode(struct super_block *sb, kuid_t kuid) -{ - struct inode *inode; - - inode = new_inode(sb); - if (!inode) - return NULL; - - inode->i_ino = get_next_ino(); - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); - inode->i_op = &proc_uid_def_inode_operations; - inode->i_uid = kuid; - - return inode; -} - -static struct dentry *proc_uident_instantiate(struct dentry *dentry, - struct task_struct *unused, const void *ptr) -{ - const struct uid_entry *u = ptr; - struct inode *inode; - - uid_t uid = name_to_int(&dentry->d_name); - kuid_t kuid; - bool uid_exists; - rt_mutex_lock(&proc_uid_lock); - uid_exists = uid_hash_entry_exists_locked(uid); - rt_mutex_unlock(&proc_uid_lock); - if (uid_exists) { - kuid = make_kuid(current_user_ns(), uid); - inode = proc_uid_make_inode(dentry->d_sb, kuid); - if (!inode) - return ERR_PTR(-ENOENT); - } else { - return ERR_PTR(-ENOENT); - } - - inode->i_mode = u->mode; - if (S_ISDIR(inode->i_mode)) - set_nlink(inode, 2); - if (u->iop) - inode->i_op = u->iop; - if (u->fop) - inode->i_fop = u->fop; - - return d_splice_alias(inode, dentry); -} - -static struct dentry *proc_uid_base_lookup(struct inode *dir, - struct dentry *dentry, - unsigned int flags) -{ - const struct uid_entry *u, *last; - unsigned int nents = ARRAY_SIZE(uid_base_stuff); - - if (nents == 0) - return ERR_PTR(-ENOENT); - - last = &uid_base_stuff[nents - 1]; - for (u = uid_base_stuff; u <= last; u++) { - if (u->len != dentry->d_name.len) - continue; - if (!memcmp(dentry->d_name.name, u->name, u->len)) - break; - } - if (u > last) - return ERR_PTR(-ENOENT); - - return proc_uident_instantiate(dentry, NULL, u); -} - -static int proc_uid_base_readdir(struct file *file, struct dir_context *ctx) -{ - unsigned int nents = ARRAY_SIZE(uid_base_stuff); - const struct uid_entry *u; - - if (!dir_emit_dots(file, ctx)) - return 0; - - if (ctx->pos >= nents + 2) - return 0; - - for (u = uid_base_stuff + (ctx->pos - 2); - u < uid_base_stuff + nents; u++) { - if (!proc_fill_cache(file, ctx, u->name, u->len, - proc_uident_instantiate, NULL, u)) - break; - ctx->pos++; - } - - return 0; -} - -static const struct inode_operations proc_uid_base_inode_operations = { - .lookup = proc_uid_base_lookup, - .setattr = proc_setattr, -}; - -static const struct file_operations proc_uid_base_operations = { - .read = generic_read_dir, - .iterate = proc_uid_base_readdir, - .llseek = default_llseek, -}; - -static struct dentry *proc_uid_instantiate(struct dentry *dentry, - struct task_struct *unused, const void *ptr) -{ - unsigned int i, len; - nlink_t nlinks; - kuid_t *kuid = (kuid_t *)ptr; - struct inode *inode = proc_uid_make_inode(dentry->d_sb, *kuid); - - if (!inode) - return ERR_PTR(-ENOENT); - - inode->i_mode = S_IFDIR | 0555; - inode->i_op = &proc_uid_base_inode_operations; - inode->i_fop = &proc_uid_base_operations; - inode->i_flags |= S_IMMUTABLE; - - nlinks = 2; - len = ARRAY_SIZE(uid_base_stuff); - for (i = 0; i < len; ++i) { - if (S_ISDIR(uid_base_stuff[i].mode)) - ++nlinks; - } - set_nlink(inode, nlinks); - - return d_splice_alias(inode, dentry); -} - -static int proc_uid_readdir(struct file *file, struct dir_context *ctx) -{ - int last_shown, i; - unsigned long bkt; - struct uid_hash_entry *entry; - - if (!dir_emit_dots(file, ctx)) - return 0; - - i = 0; - last_shown = ctx->pos - 2; - rt_mutex_lock(&proc_uid_lock); - hash_for_each(proc_uid_hash_table, bkt, entry, hash) { - int len; - char buf[PROC_NUMBUF]; - - if (i < last_shown) - continue; - len = snprintf(buf, sizeof(buf), "%u", entry->uid); - if (!proc_fill_cache(file, ctx, buf, len, - proc_uid_instantiate, NULL, &entry->uid)) - break; - i++; - ctx->pos++; - } - rt_mutex_unlock(&proc_uid_lock); - return 0; -} - -static struct dentry *proc_uid_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - int result = -ENOENT; - - uid_t uid = name_to_int(&dentry->d_name); - bool uid_exists; - - rt_mutex_lock(&proc_uid_lock); - uid_exists = uid_hash_entry_exists_locked(uid); - rt_mutex_unlock(&proc_uid_lock); - if (uid_exists) { - kuid_t kuid = make_kuid(current_user_ns(), uid); - - return proc_uid_instantiate(dentry, NULL, &kuid); - } - return ERR_PTR(result); -} - -static const struct file_operations proc_uid_operations = { - .read = generic_read_dir, - .iterate = proc_uid_readdir, - .llseek = default_llseek, -}; - -static const struct inode_operations proc_uid_inode_operations = { - .lookup = proc_uid_lookup, - .setattr = proc_setattr, -}; - -int __init proc_uid_init(void) -{ - proc_uid = proc_mkdir("uid", NULL); - if (!proc_uid) - return -ENOMEM; - proc_uid->proc_iops = &proc_uid_inode_operations; - proc_uid->proc_fops = &proc_uid_operations; - - return 0; -} diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index eeb1be259888..89712c9a7bf5 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -201,6 +201,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_GET_ENCRYPTION_KEY_STATUS: return fscrypt_ioctl_get_key_status(file, (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_NONCE: + return fscrypt_ioctl_get_nonce(file, (void __user *)arg); + default: return -ENOTTY; } @@ -223,6 +226,7 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FS_IOC_REMOVE_ENCRYPTION_KEY: case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + case FS_IOC_GET_ENCRYPTION_NONCE: break; default: return -ENOIOCTLCMD; diff --git a/gen_headers_arm.bp b/gen_headers_arm.bp index c086330198d1..9a44b6c393db 100644 --- a/gen_headers_arm.bp +++ b/gen_headers_arm.bp @@ -913,6 +913,7 @@ gen_headers_out_arm = [ "linux/usb/g_uvc.h", "linux/usb/gadgetfs.h", "linux/usb/midi.h", + "linux/usb/raw_gadget.h", "linux/usb/tmc.h", "linux/usb/usb_ctrl_qti.h", "linux/usb/video.h", diff --git a/gen_headers_arm64.bp b/gen_headers_arm64.bp index 98419a6f04cc..9e5af918a728 100644 --- a/gen_headers_arm64.bp +++ b/gen_headers_arm64.bp @@ -909,6 +909,7 @@ gen_headers_out_arm64 = [ "linux/usb/g_uvc.h", "linux/usb/gadgetfs.h", "linux/usb/midi.h", + "linux/usb/raw_gadget.h", "linux/usb/tmc.h", "linux/usb/usb_ctrl_qti.h", "linux/usb/video.h", diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index d1dd028b33fa..1b4bf5186c1d 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -208,9 +208,6 @@ struct drm_hdmi_info { /** @y420_dc_modes: bitmap of deep color support index */ u8 y420_dc_modes; - - /* @colorimetry: bitmap of supported colorimetry modes */ - u16 colorimetry; }; /** @@ -1347,54 +1344,6 @@ struct drm_connector { /** @bad_edid_counter: track sinks that give us an EDID with invalid checksum */ unsigned bad_edid_counter; - /* - * @pt_scan_info: PT scan info obtained from the VCDB of EDID - * @it_scan_info: IT scan info obtained from the VCDB of EDID - * @ce_scan_info: CE scan info obtained from the VCDB of EDID - * @color_enc_fmt: Colorimetry encoding formats of sink - * @hdr_eotf: Electro optical transfer function obtained from HDR block - * @hdr_metadata_type_one: Metadata type one obtained from HDR block - * @hdr_max_luminance: desired max luminance obtained from HDR block - * @hdr_avg_luminance: desired avg luminance obtained from HDR block - * @hdr_min_luminance: desired min luminance obtained from HDR block - * @hdr_supported: does the sink support HDR content - * @max_tmds_char: indicates the maximum TMDS Character Rate supported - * @scdc_present: when set the sink supports SCDC functionality - * @rr_capable: when set the sink is capable of initiating an - * SCDC read request - * @supports_scramble: when set the sink supports less than - * 340Mcsc scrambling - * @flags_3d: 3D view(s) supported by the sink, see drm_edid.h - * DRM_EDID_3D_*) - */ - u8 pt_scan_info; - u8 it_scan_info; - u8 ce_scan_info; - u32 color_enc_fmt; - u32 hdr_eotf; - bool hdr_metadata_type_one; - u32 hdr_max_luminance; - u32 hdr_avg_luminance; - u32 hdr_min_luminance; - bool hdr_supported; - u8 hdr_plus_app_ver; - - /* EDID bits HDMI 2.0 - * @max_tmds_char: indicates the maximum TMDS Character Rate supported - * @scdc_present: when set the sink supports SCDC functionality - * @rr_capable: when set the sink is capable of initiating an - * SCDC read request - * @supports_scramble: when set the sink supports less than - * 340Mcsc scrambling - * @flags_3d: 3D view(s) supported by the sink, see drm_edid.h - * (DRM_EDID_3D_*) - */ - int max_tmds_char; /* in Mcsc */ - bool scdc_present; - bool rr_capable; - bool supports_scramble; - int flags_3d; - /** * @edid_corrupt: Indicates whether the last read EDID was corrupt. Used * in Displayport compliance testing - Displayport Link CTS Core 1.2 diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 5258e97f071f..02ecfdc47bd9 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1361,6 +1361,8 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux, int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, u8 status[DP_LINK_STATUS_SIZE]); +bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, + u8 real_edid_checksum); /* * DisplayPort link */ @@ -1377,8 +1379,6 @@ int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link); int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); -bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, - u8 real_edid_checksum); int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index f732a07f9e5b..b9719418c3d2 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -224,16 +224,6 @@ struct detailed_timing { DRM_EDID_YCBCR420_DC_36 | \ DRM_EDID_YCBCR420_DC_30) -#define DRM_EDID_CLRMETRY_xvYCC_601 (1 << 0) -#define DRM_EDID_CLRMETRY_xvYCC_709 (1 << 1) -#define DRM_EDID_CLRMETRY_sYCC_601 (1 << 2) -#define DRM_EDID_CLRMETRY_ADBYCC_601 (1 << 3) -#define DRM_EDID_CLRMETRY_ADB_RGB (1 << 4) -#define DRM_EDID_CLRMETRY_BT2020_CYCC (1 << 5) -#define DRM_EDID_CLRMETRY_BT2020_YCC (1 << 6) -#define DRM_EDID_CLRMETRY_BT2020_RGB (1 << 7) -#define DRM_EDID_CLRMETRY_DCI_P3 (1 << 15) - /* ELD Header Block */ #define DRM_ELD_HEADER_BLOCK_SIZE 4 @@ -292,11 +282,6 @@ struct detailed_timing { #define DRM_ELD_CEA_SAD(mnl, sad) (20 + (mnl) + 3 * (sad)) -/* HDMI 2.0 */ -#define DRM_EDID_3D_INDEPENDENT_VIEW (1 << 2) -#define DRM_EDID_3D_DUAL_VIEW (1 << 1) -#define DRM_EDID_3D_OSD_DISPARITY (1 << 0) - struct edid { u8 header[8]; /* Vendor & product info */ diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h index d7b201652f4c..0c7c750fc2c4 100644 --- a/include/dt-bindings/clock/imx8mn-clock.h +++ b/include/dt-bindings/clock/imx8mn-clock.h @@ -122,8 +122,8 @@ #define IMX8MN_CLK_I2C1 105 #define IMX8MN_CLK_I2C2 106 #define IMX8MN_CLK_I2C3 107 -#define IMX8MN_CLK_I2C4 118 -#define IMX8MN_CLK_UART1 119 +#define IMX8MN_CLK_I2C4 108 +#define IMX8MN_CLK_UART1 109 #define IMX8MN_CLK_UART2 110 #define IMX8MN_CLK_UART3 111 #define IMX8MN_CLK_UART4 112 diff --git a/include/linux/android_kabi.h b/include/linux/android_kabi.h new file mode 100644 index 000000000000..efa52953fe35 --- /dev/null +++ b/include/linux/android_kabi.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * android_kabi.h - Android kernel abi abstraction header + * + * Copyright (C) 2020 Google, Inc. + * + * Heavily influenced by rh_kabi.h which came from the RHEL/CENTOS kernel and + * was: + * Copyright (c) 2014 Don Zickus + * Copyright (c) 2015-2018 Jiri Benc + * Copyright (c) 2015 Sabrina Dubroca, Hannes Frederic Sowa + * Copyright (c) 2016-2018 Prarit Bhargava + * Copyright (c) 2017 Paolo Abeni, Larry Woodman + * + * These macros are to be used to try to help alleviate future kernel abi + * changes that will occur as LTS and other kernel patches are merged into the + * tree during a period in which the kernel abi is wishing to not be disturbed. + * + * There are two times these macros should be used: + * - Before the kernel abi is "frozen" + * Padding can be added to various kernel structures that have in the past + * been known to change over time. That will give "room" in the structure + * that can then be used when fields are added so that the structure size + * will not change. + * + * - After the kernel abi is "frozen" + * If a structure's field is changed to a type that is identical in size to + * the previous type, it can be changed with a union macro + * If a field is added to a structure, the padding fields can be used to add + * the new field in a "safe" way. + */ +#ifndef _ANDROID_KABI_H +#define _ANDROID_KABI_H + +#include + +/* + * Worker macros, don't use these, use the ones without a leading '_' + */ + +#define __ANDROID_KABI_CHECK_SIZE_ALIGN(_orig, _new) \ + union { \ + _Static_assert(sizeof(struct{_new;}) <= sizeof(struct{_orig;}), \ + __FILE__ ":" __stringify(__LINE__) ": " \ + __stringify(_new) \ + " is larger than " \ + __stringify(_orig) ); \ + _Static_assert(__alignof__(struct{_new;}) <= __alignof__(struct{_orig;}), \ + __FILE__ ":" __stringify(__LINE__) ": " \ + __stringify(_orig) \ + " is not aligned the same as " \ + __stringify(_new) ); \ + } + +#ifdef __GENKSYMS__ + +#define _ANDROID_KABI_REPLACE(_orig, _new) _orig + +#else + +#define _ANDROID_KABI_REPLACE(_orig, _new) \ + union { \ + _new; \ + struct { \ + _orig; \ + } __UNIQUE_ID(android_kabi_hide); \ + __ANDROID_KABI_CHECK_SIZE_ALIGN(_orig, _new); \ + } + +#endif /* __GENKSYMS__ */ + +#define _ANDROID_KABI_RESERVE(n) u64 android_kabi_reserved##n + + +/* + * Macros to use _before_ the ABI is frozen + */ + +/* + * ANDROID_KABI_RESERVE + * Reserve some "padding" in a structure for potential future use. + * This normally placed at the end of a structure. + * number: the "number" of the padding variable in the structure. Start with + * 1 and go up. + */ +#define ANDROID_KABI_RESERVE(number) _ANDROID_KABI_RESERVE(number) + + +/* + * Macros to use _after_ the ABI is frozen + */ + +/* + * ANDROID_KABI_USE(number, _new) + * Use a previous padding entry that was defined with ANDROID_KABI_RESERVE + * number: the previous "number" of the padding variable + * _new: the variable to use now instead of the padding variable + */ +#define ANDROID_KABI_USE(number, _new) \ + _ANDROID_KABI_REPLACE(_ANDROID_KABI_RESERVE(number), _new) + +/* + * ANDROID_KABI_USE2(number, _new1, _new2) + * Use a previous padding entry that was defined with ANDROID_KABI_RESERVE for + * two new variables that fit into 64 bits. This is good for when you do not + * want to "burn" a 64bit padding variable for a smaller variable size if not + * needed. + */ +#define ANDROID_KABI_USE2(number, _new1, _new2) \ + _ANDROID_KABI_REPLACE(_ANDROID_KABI_RESERVE(number), struct{ _new1; _new2; }) + + +#endif /* _ANDROID_KABI_H */ diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index c4458dc6a757..76371aaae2d1 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -175,9 +175,10 @@ struct ceph_msg_data { #endif /* CONFIG_BLOCK */ struct ceph_bvec_iter bvec_pos; struct { - struct page **pages; /* NOT OWNER. */ + struct page **pages; size_t length; /* total # bytes */ unsigned int alignment; /* first page */ + bool own_pages; }; struct ceph_pagelist *pagelist; }; @@ -356,8 +357,8 @@ extern void ceph_con_keepalive(struct ceph_connection *con); extern bool ceph_con_keepalive_expired(struct ceph_connection *con, unsigned long interval); -extern void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages, - size_t length, size_t alignment); +void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages, + size_t length, size_t alignment, bool own_pages); extern void ceph_msg_data_add_pagelist(struct ceph_msg *msg, struct ceph_pagelist *pagelist); #ifdef CONFIG_BLOCK diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h index e081b56f1c1d..5e601975745f 100644 --- a/include/linux/ceph/osdmap.h +++ b/include/linux/ceph/osdmap.h @@ -37,6 +37,9 @@ int ceph_spg_compare(const struct ceph_spg *lhs, const struct ceph_spg *rhs); #define CEPH_POOL_FLAG_HASHPSPOOL (1ULL << 0) /* hash pg seed and pool id together */ #define CEPH_POOL_FLAG_FULL (1ULL << 1) /* pool is full */ +#define CEPH_POOL_FLAG_FULL_QUOTA (1ULL << 10) /* pool ran out of quota, + will set FULL too */ +#define CEPH_POOL_FLAG_NEARFULL (1ULL << 11) /* pool is nearfull */ struct ceph_pg_pool_info { struct rb_node node; @@ -304,5 +307,6 @@ extern struct ceph_pg_pool_info *ceph_pg_pool_by_id(struct ceph_osdmap *map, extern const char *ceph_pg_pool_name_by_id(struct ceph_osdmap *map, u64 id); extern int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name); +u64 ceph_pg_pool_flags(struct ceph_osdmap *map, u64 id); #endif diff --git a/include/linux/ceph/rados.h b/include/linux/ceph/rados.h index 3eb0e55665b4..c004bced9b91 100644 --- a/include/linux/ceph/rados.h +++ b/include/linux/ceph/rados.h @@ -143,8 +143,10 @@ extern const char *ceph_osd_state_name(int s); /* * osd map flag bits */ -#define CEPH_OSDMAP_NEARFULL (1<<0) /* sync writes (near ENOSPC) */ -#define CEPH_OSDMAP_FULL (1<<1) /* no data writes (ENOSPC) */ +#define CEPH_OSDMAP_NEARFULL (1<<0) /* sync writes (near ENOSPC), + not set since ~luminous */ +#define CEPH_OSDMAP_FULL (1<<1) /* no data writes (ENOSPC), + not set since ~luminous */ #define CEPH_OSDMAP_PAUSERD (1<<2) /* pause all reads */ #define CEPH_OSDMAP_PAUSEWR (1<<3) /* pause all writes */ #define CEPH_OSDMAP_PAUSEREC (1<<4) /* pause recovery */ diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 3ba3e6da13a6..57577075d204 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -62,6 +62,7 @@ struct css_task_iter { struct list_head *mg_tasks_head; struct list_head *dying_tasks_head; + struct list_head *cur_tasks_head; struct css_set *cur_cset; struct css_set *cur_dcset; struct task_struct *cur_task; diff --git a/include/linux/cpufreq_times.h b/include/linux/cpufreq_times.h index 0eb6dc9d0fe2..38272a5f3163 100644 --- a/include/linux/cpufreq_times.h +++ b/include/linux/cpufreq_times.h @@ -29,8 +29,6 @@ void cpufreq_acct_update_power(struct task_struct *p, u64 cputime); void cpufreq_times_create_policy(struct cpufreq_policy *policy); void cpufreq_times_record_transition(struct cpufreq_policy *policy, unsigned int new_freq); -void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end); -int single_uid_time_in_state_open(struct inode *inode, struct file *file); #else static inline void cpufreq_task_times_init(struct task_struct *p) {} static inline void cpufreq_task_times_alloc(struct task_struct *p) {} @@ -40,7 +38,5 @@ static inline void cpufreq_acct_update_power(struct task_struct *p, static inline void cpufreq_times_create_policy(struct cpufreq_policy *policy) {} static inline void cpufreq_times_record_transition( struct cpufreq_policy *policy, unsigned int new_freq) {} -static inline void cpufreq_task_times_remove_uids(uid_t uid_start, - uid_t uid_end) {} #endif /* CONFIG_CPU_FREQ_TIMES */ #endif /* _LINUX_CPUFREQ_TIMES_H */ diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 04c20de66afc..7f1478c26a33 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -55,8 +55,6 @@ extern void cpuset_init_smp(void); extern void cpuset_force_rebuild(void); extern void cpuset_update_active_cpus(void); extern void cpuset_wait_for_hotplug(void); -extern void cpuset_read_lock(void); -extern void cpuset_read_unlock(void); extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); extern void cpuset_cpus_allowed_fallback(struct task_struct *p); extern nodemask_t cpuset_mems_allowed(struct task_struct *p); @@ -178,9 +176,6 @@ static inline void cpuset_update_active_cpus(void) static inline void cpuset_wait_for_hotplug(void) { } -static inline void cpuset_read_lock(void) { } -static inline void cpuset_read_unlock(void) { } - static inline void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask) { diff --git a/include/linux/device.h b/include/linux/device.h index 5ae8491915fe..212809b6fdb5 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -26,6 +26,7 @@ #include #include #include +#include #include struct device; @@ -152,6 +153,11 @@ struct bus_type { struct lock_class_key lock_key; bool need_parent_lock; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; extern int __must_check bus_register(struct bus_type *bus); @@ -406,6 +412,11 @@ struct device_driver { void (*coredump) (struct device *dev); struct driver_private *p; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; @@ -610,6 +621,11 @@ struct class { const struct dev_pm_ops *pm; struct subsys_private *p; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; struct class_dev_iter { @@ -1351,6 +1367,14 @@ struct device { bool dma_coherent_hint_cached:1; #endif + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); + ANDROID_KABI_RESERVE(5); + ANDROID_KABI_RESERVE(6); + ANDROID_KABI_RESERVE(7); + ANDROID_KABI_RESERVE(8); }; static inline struct device *kobj_to_dev(struct kobject *kobj) diff --git a/include/linux/dmar.h b/include/linux/dmar.h index a7cf3599d9a1..f397e52c2d9d 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -69,19 +69,23 @@ struct dmar_pci_notify_info { extern struct rw_semaphore dmar_global_lock; extern struct list_head dmar_drhd_units; -#define for_each_drhd_unit(drhd) \ - list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) +#define for_each_drhd_unit(drhd) \ + list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \ + dmar_rcu_check()) #define for_each_active_drhd_unit(drhd) \ - list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \ + list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \ + dmar_rcu_check()) \ if (drhd->ignored) {} else #define for_each_active_iommu(i, drhd) \ - list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \ + list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \ + dmar_rcu_check()) \ if (i=drhd->iommu, drhd->ignored) {} else #define for_each_iommu(i, drhd) \ - list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \ + list_for_each_entry_rcu(drhd, &dmar_drhd_units, list, \ + dmar_rcu_check()) \ if (i=drhd->iommu, 0) {} else static inline bool dmar_rcu_check(void) diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h index 0aa803c451a3..c620d9139c28 100644 --- a/include/linux/dsa/8021q.h +++ b/include/linux/dsa/8021q.h @@ -28,8 +28,6 @@ int dsa_8021q_rx_switch_id(u16 vid); int dsa_8021q_rx_source_port(u16 vid); -struct sk_buff *dsa_8021q_remove_header(struct sk_buff *skb); - #else int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, @@ -64,11 +62,6 @@ int dsa_8021q_rx_source_port(u16 vid) return 0; } -struct sk_buff *dsa_8021q_remove_header(struct sk_buff *skb) -{ - return NULL; -} - #endif /* IS_ENABLED(CONFIG_NET_DSA_TAG_8021Q) */ #endif /* _NET_DSA_8021Q_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index b960ff073217..7b756b5c7872 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -407,6 +408,11 @@ struct address_space_operations { int (*swap_activate)(struct swap_info_struct *sis, struct file *file, sector_t *span); void (*swap_deactivate)(struct file *file); + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; extern const struct address_space_operations empty_aops; @@ -462,6 +468,11 @@ struct address_space { spinlock_t private_lock; struct list_head private_list; void *private_data; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } __attribute__((aligned(sizeof(long)))) __randomize_layout; /* * On most architectures that alignment is already the case; but @@ -506,6 +517,11 @@ struct block_device { int bd_fsfreeze_count; /* Mutex for freeze */ struct mutex bd_fsfreeze_mutex; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } __randomize_layout; /* XArray tags, for tagging dirty and writeback pages in the pagecache. */ @@ -698,6 +714,7 @@ struct inode { struct rcu_head i_rcu; }; atomic64_t i_version; + atomic64_t i_sequence; /* see futex */ atomic_t i_count; atomic_t i_dio_count; atomic_t i_writecount; @@ -735,6 +752,9 @@ struct inode { #endif void *i_private; /* fs or device private pointer */ + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); } __randomize_layout; struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode); @@ -1029,6 +1049,9 @@ struct file_lock; struct file_lock_operations { void (*fl_copy_lock)(struct file_lock *, struct file_lock *); void (*fl_release_private)(struct file_lock *); + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); }; struct lock_manager_operations { @@ -1039,6 +1062,9 @@ struct lock_manager_operations { bool (*lm_break)(struct file_lock *); int (*lm_change)(struct file_lock *, int, struct list_head *); void (*lm_setup)(struct file_lock *, void **); + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); }; struct lock_manager { @@ -1112,6 +1138,10 @@ struct file_lock { unsigned int debug_id; } afs; } fl_u; + + struct list_head android_reserved1; /* not a macro as we might just need it as-is */ + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); } __randomize_layout; struct file_lock_context { @@ -1558,6 +1588,11 @@ struct super_block { spinlock_t s_inode_wblist_lock; struct list_head s_inodes_wb; /* writeback inodes */ + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } __randomize_layout; /* Helper functions so that in most cases filesystems will @@ -1879,6 +1914,11 @@ struct file_operations { struct file *file_out, loff_t pos_out, loff_t len, unsigned int remap_flags); int (*fadvise)(struct file *, loff_t, loff_t, int); + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } __randomize_layout; struct inode_operations { @@ -1911,6 +1951,11 @@ struct inode_operations { umode_t create_mode); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*set_acl)(struct inode *, struct posix_acl *, int); + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } ____cacheline_aligned; static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio, @@ -1999,6 +2044,11 @@ struct super_operations { struct shrink_control *); long (*free_cached_objects)(struct super_block *, struct shrink_control *); + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; /* @@ -2268,6 +2318,11 @@ struct file_system_type { struct lock_class_key i_lock_key; struct lock_class_key i_mutex_key; struct lock_class_key i_mutex_dir_key; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; #define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME) diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 6327b9aa1c6b..df201b0f7d2f 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -144,6 +144,7 @@ extern int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags); extern int fscrypt_ioctl_set_policy(struct file *, const void __user *); extern int fscrypt_ioctl_get_policy(struct file *, void __user *); extern int fscrypt_ioctl_get_policy_ex(struct file *, void __user *); +extern int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg); extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_inherit_context(struct inode *, struct inode *, void *, bool); @@ -307,6 +308,11 @@ static inline int fscrypt_ioctl_get_policy_ex(struct file *filp, return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) { diff --git a/include/linux/futex.h b/include/linux/futex.h index 5cc3fed27d4c..b70df27d7e85 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -31,23 +31,26 @@ struct task_struct; union futex_key { struct { + u64 i_seq; unsigned long pgoff; - struct inode *inode; - int offset; + unsigned int offset; } shared; struct { + union { + struct mm_struct *mm; + u64 __tmp; + }; unsigned long address; - struct mm_struct *mm; - int offset; + unsigned int offset; } private; struct { + u64 ptr; unsigned long word; - void *ptr; - int offset; + unsigned int offset; } both; }; -#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } } +#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = 0ULL } } #ifdef CONFIG_FUTEX enum { diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 7d3f2ced92d1..73c66a3a33ae 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -2102,14 +2102,14 @@ ieee80211_he_spr_size(const u8 *he_spr_ie) { struct ieee80211_he_spr *he_spr = (void *)he_spr_ie; u8 spr_len = sizeof(struct ieee80211_he_spr); - u32 he_spr_params; + u8 he_spr_params; /* Make sure the input is not NULL */ if (!he_spr_ie) return 0; /* Calc required length */ - he_spr_params = le32_to_cpu(he_spr->he_sr_control); + he_spr_params = he_spr->he_sr_control; if (he_spr_params & IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT) spr_len++; if (he_spr_params & IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT) diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index 39faaaf843e1..c91cf2dee12a 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -2,15 +2,10 @@ #ifndef _INET_DIAG_H_ #define _INET_DIAG_H_ 1 +#include #include -struct net; -struct sock; struct inet_hashinfo; -struct nlattr; -struct nlmsghdr; -struct sk_buff; -struct netlink_callback; struct inet_diag_handler { void (*dump)(struct sk_buff *skb, @@ -62,6 +57,17 @@ int inet_diag_bc_sk(const struct nlattr *_bc, struct sock *sk); void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk); +static inline size_t inet_diag_msg_attrs_size(void) +{ + return nla_total_size(1) /* INET_DIAG_SHUTDOWN */ + + nla_total_size(1) /* INET_DIAG_TOS */ +#if IS_ENABLED(CONFIG_IPV6) + + nla_total_size(1) /* INET_DIAG_TCLASS */ + + nla_total_size(1) /* INET_DIAG_SKV6ONLY */ +#endif + + nla_total_size(4) /* INET_DIAG_MARK */ + + nla_total_size(4); /* INET_DIAG_CLASS_ID */ +} int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, struct inet_diag_msg *r, int ext, struct user_namespace *user_ns, bool net_admin); diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 6d8bf4bdf240..1e5dad8b8e59 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -120,6 +120,8 @@ #define dmar_readq(a) readq(a) #define dmar_writeq(a,v) writeq(v,a) +#define dmar_readl(a) readl(a) +#define dmar_writel(a, v) writel(v, a) #define DMAR_VER_MAJOR(v) (((v) & 0xf0) >> 4) #define DMAR_VER_MINOR(v) ((v) & 0x0f) diff --git a/include/linux/ion.h b/include/linux/ion.h index dbcbe0cb7b08..fa86bcce6e8f 100644 --- a/include/linux/ion.h +++ b/include/linux/ion.h @@ -309,6 +309,21 @@ struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, */ int ion_free(struct ion_buffer *buffer); +/** + * ion_query_heaps_kernel - Returns information about available heaps to + * in-kernel clients. + * + * @hdata: pointer to array of struct ion_heap_data. + * @size: size of @hdata array. + * + * Returns the number of available heaps and populates @hdata with information + * regarding the same. When invoked with @size as 0, the function with return + * the number of available heaps without modifying @hdata. When the number of + * available heaps is higher than @size, @size is returned instead of the + * actual number of available heaps. + */ + +size_t ion_query_heaps_kernel(struct ion_heap_data *hdata, size_t size); #else static inline int __ion_device_add_heap(struct ion_heap *heap, @@ -380,5 +395,10 @@ static inline int ion_free(struct ion_buffer *buffer) return 0; } +static inline size_t ion_query_heaps_kernel(struct ion_heap_data *hdata, + size_t size) +{ + return 0; +} #endif /* CONFIG_ION */ #endif /* _ION_KERNEL_H */ diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index ae703ea3ef48..8faca7b52543 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -705,6 +705,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, int val); void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val); +void mod_memcg_obj_state(void *p, int idx, int val); static inline void mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, int val) @@ -1128,6 +1129,10 @@ static inline void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, __mod_node_page_state(page_pgdat(page), idx, val); } +static inline void mod_memcg_obj_state(void *p, int idx, int val) +{ +} + static inline unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order, gfp_t gfp_mask, @@ -1432,6 +1437,8 @@ static inline int memcg_cache_id(struct mem_cgroup *memcg) return memcg ? memcg->kmemcg_id : -1; } +struct mem_cgroup *mem_cgroup_from_obj(void *p); + #else static inline int memcg_kmem_charge(struct page *page, gfp_t gfp, int order) @@ -1473,6 +1480,11 @@ static inline void memcg_put_cache_ids(void) { } +static inline struct mem_cgroup *mem_cgroup_from_obj(void *p) +{ + return NULL; +} + #endif /* CONFIG_MEMCG_KMEM */ #endif /* _LINUX_MEMCONTROL_H */ diff --git a/include/linux/mm.h b/include/linux/mm.h index d612d6c5f5ab..67e18454cb14 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2705,6 +2705,10 @@ static inline bool debug_pagealloc_enabled_static(void) #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_ARCH_HAS_SET_DIRECT_MAP) extern void __kernel_map_pages(struct page *page, int numpages, int enable); +/* + * When called in DEBUG_PAGEALLOC context, the call should most likely be + * guarded by debug_pagealloc_enabled() or debug_pagealloc_enabled_static() + */ static inline void kernel_map_pages(struct page *page, int numpages, int enable) { diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 9ddfb12308e4..533d73c47c0f 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -360,6 +361,11 @@ struct vm_area_struct { struct mempolicy *vm_policy; /* NUMA policy for the VMA */ #endif struct vm_userfaultfd_ctx vm_userfaultfd_ctx; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } __randomize_layout; struct core_thread { diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 6736c032c3af..b428aa77a5e4 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -403,6 +403,7 @@ struct mmc_host { MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | \ MMC_CAP_UHS_DDR50) #define MMC_CAP_SYNC_RUNTIME_PM (1 << 21) /* Synced runtime PM suspends. */ +#define MMC_CAP_NEED_RSP_BUSY (1 << 22) /* Commands with R1B can't use R1. */ #define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */ #define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */ #define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 3073ad09064f..560df1ae3a3e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -20,6 +20,7 @@ #include #include #include +#include #include /* Free memory management - zoned buddy allocator. */ @@ -580,6 +581,11 @@ struct zone { /* Zone statistics */ atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; atomic_long_t vm_numa_stat[NR_VM_NUMA_STAT_ITEMS]; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } ____cacheline_internodealigned_in_smp; enum pgdat_flags { diff --git a/include/linux/module.h b/include/linux/module.h index 34027a495180..996e81a51fbf 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -514,6 +515,10 @@ struct module { struct error_injection_entry *ei_funcs; unsigned int num_ei_funcs; #endif + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } ____cacheline_aligned __randomize_layout; #ifndef MODULE_ARCH_INIT #define MODULE_ARCH_INIT {} diff --git a/include/linux/mount.h b/include/linux/mount.h index 20541916e360..40714c6040e4 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -16,6 +16,7 @@ #include #include #include +#include struct super_block; struct vfsmount; @@ -69,6 +70,10 @@ struct vfsmount { struct dentry *mnt_root; /* root of the mounted tree */ struct super_block *mnt_sb; /* pointer to superblock */ int mnt_flags; + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); void *data; } __randomize_layout; diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 1bf83c8fcaa7..77de28bfefb0 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -311,7 +311,7 @@ static inline int TestClearPage##uname(struct page *page) { return 0; } __PAGEFLAG(Locked, locked, PF_NO_TAIL) PAGEFLAG(Waiters, waiters, PF_ONLY_HEAD) __CLEARPAGEFLAG(Waiters, waiters, PF_ONLY_HEAD) -PAGEFLAG(Error, error, PF_NO_COMPOUND) TESTCLEARFLAG(Error, error, PF_NO_COMPOUND) +PAGEFLAG(Error, error, PF_NO_TAIL) TESTCLEARFLAG(Error, error, PF_NO_TAIL) PAGEFLAG(Referenced, referenced, PF_HEAD) TESTCLEARFLAG(Referenced, referenced, PF_HEAD) __SETPAGEFLAG(Referenced, referenced, PF_HEAD) diff --git a/include/linux/phy.h b/include/linux/phy.h index 3d5d53313e6c..2b3726ff9801 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -336,6 +337,7 @@ struct phy_c45_device_ids { * is_gigabit_capable: Set to true if PHY supports 1000Mbps * has_fixups: Set to true if this phy has fixups/quirks. * suspended: Set to true if this phy has been suspended successfully. + * suspended_by_mdio_bus: Set to true if this phy was suspended by MDIO bus. * sysfs_links: Internal boolean tracking sysfs symbolic links setup/removal. * loopback_enabled: Set true if this phy has been loopbacked successfully. * state: state of the PHY for management purposes @@ -372,6 +374,7 @@ struct phy_device { unsigned is_gigabit_capable:1; unsigned has_fixups:1; unsigned suspended:1; + unsigned suspended_by_mdio_bus:1; unsigned sysfs_links:1; unsigned loopback_enabled:1; @@ -440,6 +443,11 @@ struct phy_device { void (*phy_link_change)(struct phy_device *, bool up, bool do_carrier); void (*adjust_link)(struct net_device *dev); + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; #define to_phy_device(d) container_of(to_mdio_device(d), \ struct phy_device, mdio) @@ -524,6 +532,7 @@ struct phy_driver { /* * Checks if the PHY generated an interrupt. * For multi-PHY devices with shared PHY interrupt pin + * Set interrupt bits have to be cleared. */ int (*did_interrupt)(struct phy_device *phydev); @@ -628,6 +637,10 @@ struct phy_driver { struct ethtool_tunable *tuna, const void *data); int (*set_loopback)(struct phy_device *dev, bool enable); + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + }; #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \ struct phy_driver, mdiodrv) diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index f2688404d1cd..569f446502be 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -24,7 +24,7 @@ struct platform_device { int id; bool id_auto; struct device dev; - u64 dma_mask; + u64 platform_dma_mask; u32 num_resources; struct resource *resource; diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h index ad19e68e1fc3..ae94dcebd936 100644 --- a/include/linux/power/charger-manager.h +++ b/include/linux/power/charger-manager.h @@ -248,7 +248,7 @@ struct charger_manager { u64 charging_end_time; }; -#ifdef CONFIG_CHARGER_MANAGER +#if IS_ENABLED(CONFIG_CHARGER_MANAGER) extern void cm_notify_event(struct power_supply *psy, enum cm_event_types type, char *msg); #else diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index bd0d3225f245..8670e90c1d51 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -328,6 +328,11 @@ struct power_supply_battery_ocv_table { int capacity; /* percent */ }; +struct power_supply_resistance_temp_table { + int temp; /* celsius */ + int resistance; /* internal resistance percent */ +}; + #define POWER_SUPPLY_OCV_TEMP_MAX 20 /* @@ -352,6 +357,8 @@ struct power_supply_battery_info { int ocv_temp[POWER_SUPPLY_OCV_TEMP_MAX];/* celsius */ struct power_supply_battery_ocv_table *ocv_table[POWER_SUPPLY_OCV_TEMP_MAX]; int ocv_table_size[POWER_SUPPLY_OCV_TEMP_MAX]; + struct power_supply_resistance_temp_table *resist_table; + int resist_table_size; }; extern struct atomic_notifier_head power_supply_notifier; @@ -384,6 +391,9 @@ power_supply_find_ocv2cap_table(struct power_supply_battery_info *info, int temp, int *table_len); extern int power_supply_batinfo_ocv2cap(struct power_supply_battery_info *info, int ocv, int temp); +extern int +power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table, + int table_len, int temp); extern void power_supply_changed(struct power_supply *psy); extern int power_supply_am_i_supplied(struct power_supply *psy); extern int power_supply_set_input_current_limit_from_supplier( diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 35e83f86e51a..a705aa2d03f9 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -131,12 +131,6 @@ static inline struct pid *tgid_pidfd_to_pid(const struct file *file) #endif /* CONFIG_PROC_FS */ -#ifdef CONFIG_PROC_UID -extern void proc_register_uid(kuid_t uid); -#else -static inline void proc_register_uid(kuid_t uid) {} -#endif - struct net; static inline struct proc_dir_entry *proc_net_mkdir( diff --git a/include/linux/sched.h b/include/linux/sched.h index ca0c2be16971..92701ff6a505 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -31,6 +31,7 @@ #include #include #include +#include /* task_struct member predeclarations (sorted alphabetically): */ struct audit_context; @@ -532,6 +533,11 @@ struct sched_entity { */ struct sched_avg avg; #endif + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; struct cpu_cycle_counter_cb { @@ -647,6 +653,11 @@ struct sched_rt_entity { /* rq "owned" by this entity/group: */ struct rt_rq *my_q; #endif + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } __randomize_layout; struct sched_dl_entity { @@ -1456,6 +1467,15 @@ struct task_struct { unsigned long prev_lowest_stack; #endif + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); + ANDROID_KABI_RESERVE(5); + ANDROID_KABI_RESERVE(6); + ANDROID_KABI_RESERVE(7); + ANDROID_KABI_RESERVE(8); + /* * New fields for task_struct should be added above here, so that * they are included in the randomized portion of task_struct. diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 88050259c466..f7d3466b4259 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -10,6 +10,7 @@ #include #include #include +#include /* * Types defining task->signal and task->sighand and APIs using them: @@ -225,6 +226,10 @@ struct signal_struct { struct mutex cred_guard_mutex; /* guard against foreign influences on * credential calculations * (notably. ptrace) */ + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); } __randomize_layout; /* diff --git a/include/linux/selection.h b/include/linux/selection.h index e2c1f96bf059..5b890ef5b59f 100644 --- a/include/linux/selection.h +++ b/include/linux/selection.h @@ -11,8 +11,8 @@ #include #include -extern struct vc_data *sel_cons; struct tty_struct; +struct vc_data; extern void clear_selection(void); extern int set_selection_user(const struct tiocl_selection __user *sel, @@ -24,6 +24,8 @@ extern int sel_loadlut(char __user *p); extern int mouse_reporting(void); extern void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry); +bool vc_is_sel(struct vc_data *vc); + extern int console_blanked; extern const unsigned char color_table[]; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 6ae88b0c1c31..955e1370f033 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -634,8 +634,8 @@ typedef unsigned char *sk_buff_data_t; * @offload_l3_fwd_mark: Packet was L3-forwarded in hardware * @tc_skip_classify: do not classify packet. set by IFB device * @tc_at_ingress: used within tc_classify to distinguish in/egress - * @tc_redirected: packet was redirected by a tc action - * @tc_from_ingress: if tc_redirected, tc_at_ingress at time of redirect + * @redirected: packet was redirected by packet classifier + * @from_ingress: packet was redirected from the ingress path * @peeked: this packet has been seen already, so stats have been * done for it, don't do them again * @nf_trace: netfilter packet trace flag @@ -816,8 +816,10 @@ struct sk_buff { #ifdef CONFIG_NET_CLS_ACT __u8 tc_skip_classify:1; __u8 tc_at_ingress:1; - __u8 tc_redirected:1; - __u8 tc_from_ingress:1; +#endif +#ifdef CONFIG_NET_REDIRECT + __u8 redirected:1; + __u8 from_ingress:1; #endif #ifdef CONFIG_TLS_DEVICE __u8 decrypted:1; @@ -4514,5 +4516,31 @@ static inline __wsum lco_csum(struct sk_buff *skb) return csum_partial(l4_hdr, csum_start - l4_hdr, partial); } +static inline bool skb_is_redirected(const struct sk_buff *skb) +{ +#ifdef CONFIG_NET_REDIRECT + return skb->redirected; +#else + return false; +#endif +} + +static inline void skb_set_redirected(struct sk_buff *skb, bool from_ingress) +{ +#ifdef CONFIG_NET_REDIRECT + skb->redirected = 1; + skb->from_ingress = from_ingress; + if (skb->from_ingress) + skb->tstamp = 0; +#endif +} + +static inline void skb_reset_redirect(struct sk_buff *skb) +{ +#ifdef CONFIG_NET_REDIRECT + skb->redirected = 0; +#endif +} + #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/include/linux/usb.h b/include/linux/usb.h index e656e7b4b1e4..a39eb4f608fe 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -22,6 +22,7 @@ #include /* for current && schedule_timeout */ #include /* for struct mutex */ #include /* for runtime PM */ +#include struct usb_device; struct usb_driver; @@ -257,6 +258,11 @@ struct usb_interface { struct device dev; /* interface specific device info */ struct device *usb_dev; struct work_struct reset_ws; /* for resets in atomic context */ + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) @@ -402,6 +408,11 @@ struct usb_host_bos { struct usb_ssp_cap_descriptor *ssp_cap; struct usb_ss_container_id_descriptor *ss_id; struct usb_ptm_cap_descriptor *ptm_cap; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; int __usb_get_extra_descriptor(char *buffer, unsigned size, @@ -465,6 +476,11 @@ struct usb_bus { struct mon_bus *mon_bus; /* non-null when associated */ int monitored; /* non-zero when monitored */ #endif + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; struct usb_dev_state; @@ -708,6 +724,11 @@ struct usb_device { unsigned lpm_disable_count; u16 hub_delay; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; #define to_usb_device(d) container_of(d, struct usb_device, dev) @@ -1207,6 +1228,11 @@ struct usb_driver { unsigned int supports_autosuspend:1; unsigned int disable_hub_initiated_lpm:1; unsigned int soft_unbind:1; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; #define to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver) @@ -1584,6 +1610,10 @@ struct urb { usb_complete_t complete; /* (in) completion routine */ struct usb_iso_packet_descriptor iso_frame_desc[0]; /* (in) ISO ONLY */ + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; /* ----------------------------------------------------------------------- */ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 712b2a603645..c5b171d95059 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -25,6 +25,7 @@ #include #include #include +#include #define MAX_TOPO_LEVEL 6 @@ -225,6 +226,11 @@ struct usb_hcd { * (ohci 32, uhci 1024, ehci 256/512/1024). */ + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); + /* The HC driver's private data is stored at the end of * this structure. */ @@ -410,6 +416,10 @@ struct hc_driver { /* Call for power on/off the port if necessary */ int (*port_power)(struct usb_hcd *hcd, int portnum, bool enable); + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd) @@ -560,6 +570,11 @@ struct usb_tt { spinlock_t lock; struct list_head clear_list; /* of usb_tt_clear */ struct work_struct clear_work; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; struct usb_tt_clear { diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index d8860f2d0976..e39a261a3ee4 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -23,6 +23,8 @@ #ifndef __LINUX_USB_USBNET_H #define __LINUX_USB_USBNET_H +#include + /* interface from usbnet core to each USB networking link we handle */ struct usbnet { /* housekeeping */ @@ -83,6 +85,11 @@ struct usbnet { # define EVENT_LINK_CHANGE 11 # define EVENT_SET_RX_MODE 12 # define EVENT_NO_IP_ALIGN 13 + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); }; static inline struct usb_driver *driver_of(struct usb_interface *intf) @@ -172,6 +179,9 @@ struct driver_info { int out; /* tx endpoint */ unsigned long data; /* Misc driver specific data */ + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); }; /* Minidrivers are just drivers using the "usbnet" core as a powerful diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 4e7809408073..decac0790fc1 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -126,8 +126,9 @@ extern int remap_vmalloc_range_partial(struct vm_area_struct *vma, extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, unsigned long pgoff); -void vmalloc_sync_all(void); - +void vmalloc_sync_mappings(void); +void vmalloc_sync_unmappings(void); + /* * Lowlevel-APIs (not for driver use!) */ diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 8dc77e40bc03..ded5c48598f3 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -135,7 +135,7 @@ extern int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt); int vty_init(const struct file_operations *console_fops); -extern char vt_dont_switch; +extern bool vt_dont_switch; extern int default_utf8; extern int global_cursor_default; diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 4261d1c6e87b..71726c98c5a0 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -14,6 +14,7 @@ #include #include #include +#include struct workqueue_struct; @@ -106,6 +107,8 @@ struct work_struct { #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); }; #define WORK_DATA_INIT() ATOMIC_LONG_INIT((unsigned long)WORK_STRUCT_NO_POOL) @@ -119,6 +122,9 @@ struct delayed_work { /* target workqueue and CPU ->timer uses to queue ->work */ struct workqueue_struct *wq; int cpu; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); }; struct rcu_work { diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h index 53b4dbb4ae8e..b5b3e00c8e6a 100644 --- a/include/media/v4l2-fh.h +++ b/include/media/v4l2-fh.h @@ -53,9 +53,7 @@ struct v4l2_fh { unsigned int navailable; u32 sequence; -#if IS_ENABLED(CONFIG_V4L2_MEM2MEM_DEV) struct v4l2_m2m_ctx *m2m_ctx; -#endif }; /** diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 1abae3c340a5..299240df79e4 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -58,9 +58,7 @@ int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t, rxrpc_user_attach_call_t, unsigned long, gfp_t, unsigned int); void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64); -bool rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *, - u32 *); -void rxrpc_kernel_probe_life(struct socket *, struct rxrpc_call *); +bool rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *); u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *); bool rxrpc_kernel_get_reply_time(struct socket *, struct rxrpc_call *, ktime_t *); diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 20dcadd8eed9..7fed3193f81d 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -108,6 +108,7 @@ struct fib_rule_notifier_info { [FRA_OIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \ [FRA_PRIORITY] = { .type = NLA_U32 }, \ [FRA_FWMARK] = { .type = NLA_U32 }, \ + [FRA_TUN_ID] = { .type = NLA_U64 }, \ [FRA_FWMASK] = { .type = NLA_U32 }, \ [FRA_TABLE] = { .type = NLA_U32 }, \ [FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \ diff --git a/include/net/ndisc.h b/include/net/ndisc.h index b5ebeb3b0de0..5ffba5a4e5c5 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -41,6 +41,7 @@ enum { ND_OPT_DNSSL = 31, /* RFC6106 */ ND_OPT_6CO = 34, /* RFC6775 */ ND_OPT_CAPTIVE_PORTAL = 37, /* RFC7710 */ + ND_OPT_PREF64 = 38, /* RFC-ietf-6man-ra-pref64-09 */ __ND_OPT_MAX }; diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index d334e4609dd4..9fb7cf1cdf36 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -675,22 +675,6 @@ void __qdisc_calculate_pkt_len(struct sk_buff *skb, const struct qdisc_size_table *stab); int skb_do_redirect(struct sk_buff *); -static inline void skb_reset_tc(struct sk_buff *skb) -{ -#ifdef CONFIG_NET_CLS_ACT - skb->tc_redirected = 0; -#endif -} - -static inline bool skb_is_tc_redirected(const struct sk_buff *skb) -{ -#ifdef CONFIG_NET_CLS_ACT - return skb->tc_redirected; -#else - return false; -#endif -} - static inline bool skb_at_tc_ingress(const struct sk_buff *skb) { #ifdef CONFIG_NET_CLS_ACT diff --git a/include/net/sock.h b/include/net/sock.h index 6c5a3809483e..7471c16c8edd 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -68,6 +68,7 @@ #include #include #include +#include /* * This structure really needs to be cleaned up. @@ -511,6 +512,15 @@ struct sock { struct bpf_sk_storage __rcu *sk_bpf_storage; #endif struct rcu_head sk_rcu; + + ANDROID_KABI_RESERVE(1); + ANDROID_KABI_RESERVE(2); + ANDROID_KABI_RESERVE(3); + ANDROID_KABI_RESERVE(4); + ANDROID_KABI_RESERVE(5); + ANDROID_KABI_RESERVE(6); + ANDROID_KABI_RESERVE(7); + ANDROID_KABI_RESERVE(8); }; enum sk_pacing { diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h index 564ba1b5cf57..c612cabbc378 100644 --- a/include/trace/events/afs.h +++ b/include/trace/events/afs.h @@ -233,7 +233,7 @@ enum afs_cb_break_reason { EM(afs_call_trace_get, "GET ") \ EM(afs_call_trace_put, "PUT ") \ EM(afs_call_trace_wake, "WAKE ") \ - E_(afs_call_trace_work, "WORK ") + E_(afs_call_trace_work, "QUEUE") #define afs_server_traces \ EM(afs_server_trace_alloc, "ALLOC ") \ diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 0c9a8b81d357..320a6381576e 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -166,6 +166,7 @@ struct fscrypt_get_key_status_arg { #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg) #define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg) +#define FS_IOC_GET_ENCRYPTION_NONCE _IOR('f', 27, __u8[16]) /**********************************************************************/ diff --git a/include/uapi/linux/incrementalfs.h b/include/uapi/linux/incrementalfs.h index b257b9f0ec3f..2d535d365ce9 100644 --- a/include/uapi/linux/incrementalfs.h +++ b/include/uapi/linux/incrementalfs.h @@ -35,6 +35,8 @@ #define INCFS_XATTR_METADATA_NAME (XATTR_USER_PREFIX "incfs.metadata") #define INCFS_MAX_SIGNATURE_SIZE 8096 +#define INCFS_SIGNATURE_VERSION 2 +#define INCFS_SIGNATURE_SECTIONS 2 #define INCFS_IOCTL_BASE_CODE 'g' @@ -46,7 +48,49 @@ /* Read file signature */ #define INCFS_IOC_READ_FILE_SIGNATURE \ - _IOWR(INCFS_IOCTL_BASE_CODE, 31, struct incfs_get_file_sig_args) + _IOR(INCFS_IOCTL_BASE_CODE, 31, struct incfs_get_file_sig_args) + +/* + * Fill in one or more data block. This may only be called on a handle + * passed as a parameter to INCFS_IOC_PERMIT_FILLING + * + * Returns number of blocks filled in, or error if none were + */ +#define INCFS_IOC_FILL_BLOCKS \ + _IOR(INCFS_IOCTL_BASE_CODE, 32, struct incfs_fill_blocks) + +/* + * Permit INCFS_IOC_FILL_BLOCKS on the given file descriptor + * May only be called on .pending_reads file + * + * Returns 0 on success or error + */ +#define INCFS_IOC_PERMIT_FILL \ + _IOW(INCFS_IOCTL_BASE_CODE, 33, struct incfs_permit_fill) + +/* + * Fills buffer with ranges of populated blocks + * + * Returns 0 if all ranges written + * error otherwise + * + * Either way, range_buffer_size_out is set to the number + * of bytes written. Should be set to 0 by caller. The ranges + * filled are valid, but if an error was returned there might + * be more ranges to come. + * + * Ranges are ranges of filled blocks: + * + * 1 2 7 9 + * + * means blocks 1, 2, 7, 8, 9 are filled, 0, 3, 4, 5, 6 and 10 on + * are not + * + * If hashing is enabled for the file, the hash blocks are simply + * treated as though they immediately followed the data blocks. + */ +#define INCFS_IOC_GET_FILLED_BLOCKS \ + _IOR(INCFS_IOCTL_BASE_CODE, 34, struct incfs_get_filled_blocks_args) enum incfs_compression_alg { COMPRESSION_NONE = 0, @@ -81,10 +125,9 @@ struct incfs_pending_read_info { }; /* - * A struct to be written into a control file to load a data or hash - * block to a data file. + * Description of a data or hash block to add to a data file. */ -struct incfs_new_data_block { +struct incfs_fill_block { /* Index of a data block. */ __u32 block_index; @@ -114,51 +157,35 @@ struct incfs_new_data_block { __aligned_u64 reserved3; }; +/* + * Description of a number of blocks to add to a data file + * + * Argument for INCFS_IOC_FILL_BLOCKS + */ +struct incfs_fill_blocks { + /* Number of blocks */ + __u64 count; + + /* A pointer to an array of incfs_fill_block structs */ + __aligned_u64 fill_blocks; +}; + +/* + * Permit INCFS_IOC_FILL_BLOCKS on the given file descriptor + * May only be called on .pending_reads file + * + * Argument for INCFS_IOC_PERMIT_FILL + */ +struct incfs_permit_fill { + /* File to permit fills on */ + __u32 file_descriptor; +}; + enum incfs_hash_tree_algorithm { INCFS_HASH_TREE_NONE = 0, INCFS_HASH_TREE_SHA256 = 1 }; -struct incfs_file_signature_info { - /* - * A pointer to file's root hash (if determined != 0) - * Actual hash size determined by hash_tree_alg. - * Size of the buffer should be at least INCFS_MAX_HASH_SIZE - * - * Equivalent to: u8 *root_hash; - */ - __aligned_u64 root_hash; - - /* - * A pointer to additional data that was attached to the root hash - * before signing. - * - * Equivalent to: u8 *additional_data; - */ - __aligned_u64 additional_data; - - /* Size of additional data. */ - __u32 additional_data_size; - - __u32 reserved1; - - /* - * A pointer to pkcs7 signature DER blob. - * - * Equivalent to: u8 *signature; - */ - __aligned_u64 signature; - - - /* Size of pkcs7 signature DER blob */ - __u32 signature_size; - - __u32 reserved2; - - /* Value from incfs_hash_tree_algorithm */ - __u8 hash_tree_alg; -}; - /* * Create a new file or directory. */ @@ -212,10 +239,30 @@ struct incfs_new_file_args { __u32 reserved4; - /* struct incfs_file_signature_info *signature_info; */ + /* + * Points to an APK V4 Signature data blob + * Signature must have two sections + * Format is: + * u32 version + * u32 size_of_hash_info_section + * u8 hash_info_section[] + * u32 size_of_signing_info_section + * u8 signing_info_section[] + * + * Note that incfs does not care about what is in signing_info_section + * + * hash_info_section has following format: + * u32 hash_algorithm; // Must be SHA256 == 1 + * u8 log2_blocksize; // Must be 12 for 4096 byte blocks + * u32 salt_size; + * u8 salt[]; + * u32 hash_size; + * u8 root_hash[]; + */ __aligned_u64 signature_info; - __aligned_u64 reserved5; + /* Size of signature_info */ + __aligned_u64 signature_size; __aligned_u64 reserved6; }; @@ -242,4 +289,43 @@ struct incfs_get_file_sig_args { __u32 file_signature_len_out; }; +struct incfs_filled_range { + __u32 begin; + __u32 end; +}; + +/* + * Request ranges of filled blocks + * Argument for INCFS_IOC_GET_FILLED_BLOCKS + */ +struct incfs_get_filled_blocks_args { + /* + * A buffer to populate with ranges of filled blocks + * + * Equivalent to struct incfs_filled_ranges *range_buffer + */ + __aligned_u64 range_buffer; + + /* Size of range_buffer */ + __u32 range_buffer_size; + + /* Start index to read from */ + __u32 start_index; + + /* + * End index to read to. 0 means read to end. This is a range, + * so incfs will read from start_index to end_index - 1 + */ + __u32 end_index; + + /* Actual number of blocks in file */ + __u32 total_blocks_out; + + /* Number of bytes written to range buffer */ + __u32 range_buffer_size_out; + + /* Sector scanned up to, if the call was interrupted */ + __u32 index_out; +}; + #endif /* _UAPI_LINUX_INCREMENTALFS_H */ diff --git a/include/uapi/linux/serio.h b/include/uapi/linux/serio.h index 50e991952c97..ed2a96f43ce4 100644 --- a/include/uapi/linux/serio.h +++ b/include/uapi/linux/serio.h @@ -9,7 +9,7 @@ #ifndef _UAPI_SERIO_H #define _UAPI_SERIO_H - +#include #include #define SPIOCSTYPE _IOW('q', 0x01, unsigned long) @@ -18,10 +18,10 @@ /* * bit masks for use in "interrupt" flags (3rd argument) */ -#define SERIO_TIMEOUT BIT(0) -#define SERIO_PARITY BIT(1) -#define SERIO_FRAME BIT(2) -#define SERIO_OOB_DATA BIT(3) +#define SERIO_TIMEOUT _BITUL(0) +#define SERIO_PARITY _BITUL(1) +#define SERIO_FRAME _BITUL(2) +#define SERIO_OOB_DATA _BITUL(3) /* * Serio types diff --git a/include/uapi/linux/usb/raw_gadget.h b/include/uapi/linux/usb/raw_gadget.h new file mode 100644 index 000000000000..ea375082b3ac --- /dev/null +++ b/include/uapi/linux/usb/raw_gadget.h @@ -0,0 +1,167 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * USB Raw Gadget driver. + * + * See Documentation/usb/raw-gadget.rst for more details. + */ + +#ifndef _UAPI__LINUX_USB_RAW_GADGET_H +#define _UAPI__LINUX_USB_RAW_GADGET_H + +#include +#include +#include + +/* Maximum length of driver_name/device_name in the usb_raw_init struct. */ +#define UDC_NAME_LENGTH_MAX 128 + +/* + * struct usb_raw_init - argument for USB_RAW_IOCTL_INIT ioctl. + * @speed: The speed of the emulated USB device, takes the same values as + * the usb_device_speed enum: USB_SPEED_FULL, USB_SPEED_HIGH, etc. + * @driver_name: The name of the UDC driver. + * @device_name: The name of a UDC instance. + * + * The last two fields identify a UDC the gadget driver should bind to. + * For example, Dummy UDC has "dummy_udc" as its driver_name and "dummy_udc.N" + * as its device_name, where N in the index of the Dummy UDC instance. + * At the same time the dwc2 driver that is used on Raspberry Pi Zero, has + * "20980000.usb" as both driver_name and device_name. + */ +struct usb_raw_init { + __u8 driver_name[UDC_NAME_LENGTH_MAX]; + __u8 device_name[UDC_NAME_LENGTH_MAX]; + __u8 speed; +}; + +/* The type of event fetched with the USB_RAW_IOCTL_EVENT_FETCH ioctl. */ +enum usb_raw_event_type { + USB_RAW_EVENT_INVALID = 0, + + /* This event is queued when the driver has bound to a UDC. */ + USB_RAW_EVENT_CONNECT = 1, + + /* This event is queued when a new control request arrived to ep0. */ + USB_RAW_EVENT_CONTROL = 2, + + /* The list might grow in the future. */ +}; + +/* + * struct usb_raw_event - argument for USB_RAW_IOCTL_EVENT_FETCH ioctl. + * @type: The type of the fetched event. + * @length: Length of the data buffer. Updated by the driver and set to the + * actual length of the fetched event data. + * @data: A buffer to store the fetched event data. + * + * Currently the fetched data buffer is empty for USB_RAW_EVENT_CONNECT, + * and contains struct usb_ctrlrequest for USB_RAW_EVENT_CONTROL. + */ +struct usb_raw_event { + __u32 type; + __u32 length; + __u8 data[0]; +}; + +#define USB_RAW_IO_FLAGS_ZERO 0x0001 +#define USB_RAW_IO_FLAGS_MASK 0x0001 + +static inline int usb_raw_io_flags_valid(__u16 flags) +{ + return (flags & ~USB_RAW_IO_FLAGS_MASK) == 0; +} + +static inline int usb_raw_io_flags_zero(__u16 flags) +{ + return (flags & USB_RAW_IO_FLAGS_ZERO); +} + +/* + * struct usb_raw_ep_io - argument for USB_RAW_IOCTL_EP0/EP_WRITE/READ ioctls. + * @ep: Endpoint handle as returned by USB_RAW_IOCTL_EP_ENABLE for + * USB_RAW_IOCTL_EP_WRITE/READ. Ignored for USB_RAW_IOCTL_EP0_WRITE/READ. + * @flags: When USB_RAW_IO_FLAGS_ZERO is specified, the zero flag is set on + * the submitted USB request, see include/linux/usb/gadget.h for details. + * @length: Length of data. + * @data: Data to send for USB_RAW_IOCTL_EP0/EP_WRITE. Buffer to store received + * data for USB_RAW_IOCTL_EP0/EP_READ. + */ +struct usb_raw_ep_io { + __u16 ep; + __u16 flags; + __u32 length; + __u8 data[0]; +}; + +/* + * Initializes a Raw Gadget instance. + * Accepts a pointer to the usb_raw_init struct as an argument. + * Returns 0 on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_INIT _IOW('U', 0, struct usb_raw_init) + +/* + * Instructs Raw Gadget to bind to a UDC and start emulating a USB device. + * Returns 0 on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_RUN _IO('U', 1) + +/* + * A blocking ioctl that waits for an event and returns fetched event data to + * the user. + * Accepts a pointer to the usb_raw_event struct. + * Returns 0 on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event) + +/* + * Queues an IN (OUT for READ) urb as a response to the last control request + * received on endpoint 0, provided that was an IN (OUT for READ) request and + * waits until the urb is completed. Copies received data to user for READ. + * Accepts a pointer to the usb_raw_ep_io struct as an argument. + * Returns length of trasferred data on success or negative error code on + * failure. + */ +#define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io) +#define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io) + +/* + * Finds an endpoint that supports the transfer type specified in the + * descriptor and enables it. + * Accepts a pointer to the usb_endpoint_descriptor struct as an argument. + * Returns enabled endpoint handle on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor) + +/* Disables specified endpoint. + * Accepts endpoint handle as an argument. + * Returns 0 on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32) + +/* + * Queues an IN (OUT for READ) urb as a response to the last control request + * received on endpoint usb_raw_ep_io.ep, provided that was an IN (OUT for READ) + * request and waits until the urb is completed. Copies received data to user + * for READ. + * Accepts a pointer to the usb_raw_ep_io struct as an argument. + * Returns length of trasferred data on success or negative error code on + * failure. + */ +#define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io) +#define USB_RAW_IOCTL_EP_READ _IOWR('U', 8, struct usb_raw_ep_io) + +/* + * Switches the gadget into the configured state. + * Returns 0 on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_CONFIGURE _IO('U', 9) + +/* + * Constrains UDC VBUS power usage. + * Accepts current limit in 2 mA units as an argument. + * Returns 0 on success or negative error code on failure. + */ +#define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32) + +#endif /* _UAPI__LINUX_USB_RAW_GADGET_H */ diff --git a/init/Kconfig.gki b/init/Kconfig.gki index 13badc10593b..c8a7643012a0 100644 --- a/init/Kconfig.gki +++ b/init/Kconfig.gki @@ -91,6 +91,7 @@ config GKI_HIDDEN_MEDIA_CONFIGS bool "Hidden Media configs needed for GKI" select VIDEOBUF2_CORE select MEDIA_SUPPORT + select FRAME_VECTOR help Dummy config option used to enable hidden media configs. These are normally selected implicitly when a module @@ -123,6 +124,38 @@ config GKI_LEGACY_WEXT_ALLCONFIG If you are not building a kernel to be used for a variety of out-of-kernel built wireless modules, say N here. +config GKI_HIDDEN_USB_CONFIGS + bool "Hiddel USB configurations needed for GKI" + select USB_PHY + help + Dummy config option used to enable all USB related hidden configs. + These configurations are usually only selected by another config + option or a combination of them. + + If you are not building a kernel to be used for a variety of + out-of-kernel build USB drivers, say N here. + +config GKI_HIDDEN_SOC_BUS_CONFIGS + bool "Hidden SoC bus configuration needed for GKI" + select SOC_BUS + help + Dummy config option used to enable SOC_BUS hidden Kconfig. + The configuration is required for SoCs to register themselves to the bus. + + If you are not building a kernel to be used for a variety of SoCs and + out-of-tree drivers, say N here. + +config GKI_HIDDEN_RPMSG_CONFIGS + bool "Hidden RPMSG configuration needed for GKI" + select RPMSG + help + Dummy config option used to enable the hidden RPMSG config. + This configuration is usually only selected by another config + option or a combination of them. + + If you are not building a kernel to be used for a variety of + out-of-kernel build RPMSG drivers, say N here. + # Atrocities needed for # a) building GKI modules in separate tree, or # b) building drivers that are not modularizable @@ -144,6 +177,9 @@ config GKI_HACKS_TO_FIX select GKI_HIDDEN_MEDIA_CONFIGS select GKI_HIDDEN_VIRTUAL_CONFIGS select GKI_QCOM_CLKS_CONFIGS + select GKI_HIDDEN_USB_CONFIGS + select GKI_HIDDEN_SOC_BUS_CONFIGS + select GKI_HIDDEN_RPMSG_CONFIGS help Dummy config option used to enable core functionality used by modules that may not be selectable in this config. diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 29c7c06c6bd6..b03087f110eb 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -2309,7 +2309,7 @@ static int btf_enum_check_member(struct btf_verifier_env *env, struct_size = struct_type->size; bytes_offset = BITS_ROUNDDOWN_BYTES(struct_bits_off); - if (struct_size - bytes_offset < sizeof(int)) { + if (struct_size - bytes_offset < member_type->size) { btf_verifier_log_member(env, struct_type, member, "Member exceeds struct_size"); return -EINVAL; @@ -3460,7 +3460,7 @@ int btf_get_info_by_fd(const struct btf *btf, union bpf_attr __user *uattr) { struct bpf_btf_info __user *uinfo; - struct bpf_btf_info info = {}; + struct bpf_btf_info info; u32 info_copy, btf_copy; void __user *ubtf; u32 uinfo_len; @@ -3469,6 +3469,7 @@ int btf_get_info_by_fd(const struct btf *btf, uinfo_len = attr->info.info_len; info_copy = min_t(u32, uinfo_len, sizeof(info)); + memset(&info, 0, sizeof(info)); if (copy_from_user(&info, uinfo, info_copy)) return -EFAULT; diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 8bd69062fbe5..869e2e1860e8 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -228,6 +228,9 @@ cleanup: for (i = 0; i < NR; i++) bpf_prog_array_free(arrays[i]); + for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p)) + cgroup_bpf_put(p); + percpu_ref_exit(&cgrp->bpf.refcnt); return -ENOMEM; @@ -300,8 +303,8 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, { struct list_head *progs = &cgrp->bpf.progs[type]; struct bpf_prog *old_prog = NULL; - struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE], - *old_storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {NULL}; + struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {}; + struct bpf_cgroup_storage *old_storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {}; enum bpf_cgroup_storage_type stype; struct bpf_prog_list *pl; bool pl_was_allocated; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index ace1cfaa24b6..14f4a76b44d5 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2325,7 +2325,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, union bpf_attr __user *uattr) { struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info); - struct bpf_prog_info info = {}; + struct bpf_prog_info info; u32 info_len = attr->info.info_len; struct bpf_prog_stats stats; char __user *uinsns; @@ -2337,6 +2337,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, return err; info_len = min_t(u32, sizeof(info), info_len); + memset(&info, 0, sizeof(info)); if (copy_from_user(&info, uinfo, info_len)) return -EFAULT; @@ -2600,7 +2601,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, union bpf_attr __user *uattr) { struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info); - struct bpf_map_info info = {}; + struct bpf_map_info info; u32 info_len = attr->info.info_len; int err; @@ -2609,6 +2610,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, return err; info_len = min_t(u32, sizeof(info), info_len); + memset(&info, 0, sizeof(info)); info.type = map->map_type; info.id = map->id; info.key_size = map->key_size; @@ -2836,7 +2838,7 @@ out: SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) { - union bpf_attr attr = {}; + union bpf_attr attr; int err; if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN)) @@ -2848,6 +2850,7 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz size = min_t(u32, size, sizeof(attr)); /* copy attributes from user space, may be less than sizeof(bpf_attr) */ + memset(&attr, 0, sizeof(attr)); if (copy_from_user(&attr, uattr, size) != 0) return -EFAULT; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index b2817d0929b3..a0b76b360d6f 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -979,17 +979,6 @@ static void __reg_bound_offset(struct bpf_reg_state *reg) reg->umax_value)); } -static void __reg_bound_offset32(struct bpf_reg_state *reg) -{ - u64 mask = 0xffffFFFF; - struct tnum range = tnum_range(reg->umin_value & mask, - reg->umax_value & mask); - struct tnum lo32 = tnum_cast(reg->var_off, 4); - struct tnum hi32 = tnum_lshift(tnum_rshift(reg->var_off, 32), 32); - - reg->var_off = tnum_or(hi32, tnum_intersect(lo32, range)); -} - /* Reset the min/max bounds of a register */ static void __mark_reg_unbounded(struct bpf_reg_state *reg) { @@ -5452,10 +5441,6 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg, /* We might have learned some bits from the bounds. */ __reg_bound_offset(false_reg); __reg_bound_offset(true_reg); - if (is_jmp32) { - __reg_bound_offset32(false_reg); - __reg_bound_offset32(true_reg); - } /* Intersecting with the old var_off might have improved our bounds * slightly. e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc), * then new var_off is (0; 0x7f...fc) which improves our umax. @@ -5565,10 +5550,6 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg, /* We might have learned some bits from the bounds. */ __reg_bound_offset(false_reg); __reg_bound_offset(true_reg); - if (is_jmp32) { - __reg_bound_offset32(false_reg); - __reg_bound_offset32(true_reg); - } /* Intersecting with the old var_off might have improved our bounds * slightly. e.g. if umax was 0x7f...f and var_off was (0; 0xf...fc), * then new var_off is (0; 0x7f...fc) which improves our umax. diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index aec171bcfedc..7b9ee484abab 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -473,6 +473,7 @@ static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos) */ p++; if (p >= end) { + (*pos)++; return NULL; } else { *pos = *p; @@ -784,7 +785,7 @@ void cgroup1_release_agent(struct work_struct *work) pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL); - if (!pathbuf || !agentbuf) + if (!pathbuf || !agentbuf || !strlen(agentbuf)) goto out; spin_lock_irq(&css_set_lock); diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 595c52d59f31..7c9e97553a00 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -4461,12 +4461,16 @@ static void css_task_iter_advance_css_set(struct css_task_iter *it) } } while (!css_set_populated(cset) && list_empty(&cset->dying_tasks)); - if (!list_empty(&cset->tasks)) + if (!list_empty(&cset->tasks)) { it->task_pos = cset->tasks.next; - else if (!list_empty(&cset->mg_tasks)) + it->cur_tasks_head = &cset->tasks; + } else if (!list_empty(&cset->mg_tasks)) { it->task_pos = cset->mg_tasks.next; - else + it->cur_tasks_head = &cset->mg_tasks; + } else { it->task_pos = cset->dying_tasks.next; + it->cur_tasks_head = &cset->dying_tasks; + } it->tasks_head = &cset->tasks; it->mg_tasks_head = &cset->mg_tasks; @@ -4524,10 +4528,14 @@ repeat: else it->task_pos = it->task_pos->next; - if (it->task_pos == it->tasks_head) + if (it->task_pos == it->tasks_head) { it->task_pos = it->mg_tasks_head->next; - if (it->task_pos == it->mg_tasks_head) + it->cur_tasks_head = it->mg_tasks_head; + } + if (it->task_pos == it->mg_tasks_head) { it->task_pos = it->dying_tasks_head->next; + it->cur_tasks_head = it->dying_tasks_head; + } if (it->task_pos == it->dying_tasks_head) css_task_iter_advance_css_set(it); } else { @@ -4546,11 +4554,12 @@ repeat: goto repeat; /* and dying leaders w/o live member threads */ - if (!atomic_read(&task->signal->live)) + if (it->cur_tasks_head == it->dying_tasks_head && + !atomic_read(&task->signal->live)) goto repeat; } else { /* skip all dying ones */ - if (task->flags & PF_EXITING) + if (it->cur_tasks_head == it->dying_tasks_head) goto repeat; } } @@ -4659,6 +4668,9 @@ static void *cgroup_procs_next(struct seq_file *s, void *v, loff_t *pos) struct kernfs_open_file *of = s->private; struct css_task_iter *it = of->priv; + if (pos) + (*pos)++; + return css_task_iter_next(it); } @@ -4674,7 +4686,7 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos, * from position 0, so we can simply keep iterating on !0 *pos. */ if (!it) { - if (WARN_ON_ONCE((*pos)++)) + if (WARN_ON_ONCE((*pos))) return ERR_PTR(-EINVAL); it = kzalloc(sizeof(*it), GFP_KERNEL); @@ -4682,10 +4694,11 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos, return ERR_PTR(-ENOMEM); of->priv = it; css_task_iter_start(&cgrp->self, iter_flags, it); - } else if (!(*pos)++) { + } else if (!(*pos)) { css_task_iter_end(it); css_task_iter_start(&cgrp->self, iter_flags, it); - } + } else + return it->cur_task; return cgroup_procs_next(s, NULL, NULL); } @@ -6381,6 +6394,10 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd) return; } + /* Don't associate the sock with unrelated interrupted task's cgroup. */ + if (in_interrupt()) + return; + rcu_read_lock(); while (true) { diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 9ea6269fff29..3099f47f1676 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -334,17 +334,6 @@ static struct cpuset top_cpuset = { */ DEFINE_STATIC_PERCPU_RWSEM(cpuset_rwsem); - -void cpuset_read_lock(void) -{ - percpu_down_read(&cpuset_rwsem); -} - -void cpuset_read_unlock(void) -{ - percpu_up_read(&cpuset_rwsem); -} - static DEFINE_SPINLOCK(callback_lock); static struct workqueue_struct *cpuset_migrate_mm_wq; diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index 269cd6db7981..bc5b27fd11de 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -49,6 +49,7 @@ u64 dma_direct_get_required_mask(struct device *dev) return (1ULL << (fls64(max_dma) - 1)) * 2 - 1; } +EXPORT_SYMBOL_GPL(dma_direct_get_required_mask); static gfp_t __dma_direct_optimal_gfp_mask(struct device *dev, u64 dma_mask, u64 *phys_mask) @@ -221,6 +222,7 @@ void *dma_direct_alloc(struct device *dev, size_t size, return arch_dma_alloc(dev, size, dma_handle, gfp, attrs); return dma_direct_alloc_pages(dev, size, dma_handle, gfp, attrs); } +EXPORT_SYMBOL_GPL(dma_direct_alloc); void dma_direct_free(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr, unsigned long attrs) @@ -231,6 +233,7 @@ void dma_direct_free(struct device *dev, size_t size, else dma_direct_free_pages(dev, size, cpu_addr, dma_addr, attrs); } +EXPORT_SYMBOL_GPL(dma_direct_free); #if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \ defined(CONFIG_SWIOTLB) diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c index ede39a2b9057..fe10187b7dcd 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -148,6 +148,7 @@ int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); return ret; } +EXPORT_SYMBOL_GPL(dma_common_get_sgtable); /* * The whole dma_get_sgtable() idea is fundamentally unsafe - it seems @@ -237,6 +238,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, return -ENXIO; #endif /* CONFIG_MMU */ } +EXPORT_SYMBOL_GPL(dma_common_mmap); /** * dma_can_mmap - check if a given device supports dma_mmap_* diff --git a/kernel/fork.c b/kernel/fork.c index 1eee079a3b7b..f89e8c85f2b8 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -396,8 +396,8 @@ static void account_kernel_stack(struct task_struct *tsk, int account) mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB, THREAD_SIZE / 1024 * account); - mod_memcg_page_state(first_page, MEMCG_KERNEL_STACK_KB, - account * (THREAD_SIZE / 1024)); + mod_memcg_obj_state(stack, MEMCG_KERNEL_STACK_KB, + account * (THREAD_SIZE / 1024)); } } diff --git a/kernel/futex.c b/kernel/futex.c index afbf928d6a6b..5660c02b01b0 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -385,9 +385,9 @@ static inline int hb_waiters_pending(struct futex_hash_bucket *hb) */ static struct futex_hash_bucket *hash_futex(union futex_key *key) { - u32 hash = jhash2((u32*)&key->both.word, - (sizeof(key->both.word)+sizeof(key->both.ptr))/4, + u32 hash = jhash2((u32 *)key, offsetof(typeof(*key), both.offset) / 4, key->both.offset); + return &futex_queues[hash & (futex_hashsize - 1)]; } @@ -429,7 +429,7 @@ static void get_futex_key_refs(union futex_key *key) switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { case FUT_OFF_INODE: - ihold(key->shared.inode); /* implies smp_mb(); (B) */ + smp_mb(); /* explicit smp_mb(); (B) */ break; case FUT_OFF_MMSHARED: futex_get_mm(key); /* implies smp_mb(); (B) */ @@ -463,7 +463,6 @@ static void drop_futex_key_refs(union futex_key *key) switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) { case FUT_OFF_INODE: - iput(key->shared.inode); break; case FUT_OFF_MMSHARED: mmdrop(key->private.mm); @@ -505,6 +504,46 @@ futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout, return timeout; } +/* + * Generate a machine wide unique identifier for this inode. + * + * This relies on u64 not wrapping in the life-time of the machine; which with + * 1ns resolution means almost 585 years. + * + * This further relies on the fact that a well formed program will not unmap + * the file while it has a (shared) futex waiting on it. This mapping will have + * a file reference which pins the mount and inode. + * + * If for some reason an inode gets evicted and read back in again, it will get + * a new sequence number and will _NOT_ match, even though it is the exact same + * file. + * + * It is important that match_futex() will never have a false-positive, esp. + * for PI futexes that can mess up the state. The above argues that false-negatives + * are only possible for malformed programs. + */ +static u64 get_inode_sequence_number(struct inode *inode) +{ + static atomic64_t i_seq; + u64 old; + + /* Does the inode already have a sequence number? */ + old = atomic64_read(&inode->i_sequence); + if (likely(old)) + return old; + + for (;;) { + u64 new = atomic64_add_return(1, &i_seq); + if (WARN_ON_ONCE(!new)) + continue; + + old = atomic64_cmpxchg_relaxed(&inode->i_sequence, 0, new); + if (old) + return old; + return new; + } +} + /** * get_futex_key() - Get parameters which are the keys for a futex * @uaddr: virtual address of the futex @@ -517,9 +556,15 @@ futex_setup_timer(ktime_t *time, struct hrtimer_sleeper *timeout, * * The key words are stored in @key on success. * - * For shared mappings, it's (page->index, file_inode(vma->vm_file), - * offset_within_page). For private mappings, it's (uaddr, current->mm). - * We can usually work out the index without swapping in the page. + * For shared mappings (when @fshared), the key is: + * ( inode->i_sequence, page->index, offset_within_page ) + * [ also see get_inode_sequence_number() ] + * + * For private mappings (or when !@fshared), the key is: + * ( current->mm, address, 0 ) + * + * This allows (cross process, where applicable) identification of the futex + * without keeping the page pinned for the duration of the FUTEX_WAIT. * * lock_page() might sleep, the caller should not hold a spinlock. */ @@ -659,8 +704,6 @@ again: key->private.mm = mm; key->private.address = address; - get_futex_key_refs(key); /* implies smp_mb(); (B) */ - } else { struct inode *inode; @@ -692,40 +735,14 @@ again: goto again; } - /* - * Take a reference unless it is about to be freed. Previously - * this reference was taken by ihold under the page lock - * pinning the inode in place so i_lock was unnecessary. The - * only way for this check to fail is if the inode was - * truncated in parallel which is almost certainly an - * application bug. In such a case, just retry. - * - * We are not calling into get_futex_key_refs() in file-backed - * cases, therefore a successful atomic_inc return below will - * guarantee that get_futex_key() will still imply smp_mb(); (B). - */ - if (!atomic_inc_not_zero(&inode->i_count)) { - rcu_read_unlock(); - put_page(page); - - goto again; - } - - /* Should be impossible but lets be paranoid for now */ - if (WARN_ON_ONCE(inode->i_mapping != mapping)) { - err = -EFAULT; - rcu_read_unlock(); - iput(inode); - - goto out; - } - key->both.offset |= FUT_OFF_INODE; /* inode-based key */ - key->shared.inode = inode; + key->shared.i_seq = get_inode_sequence_number(inode); key->shared.pgoff = basepage_index(tail); rcu_read_unlock(); } + get_futex_key_refs(key); /* implies smp_mb(); (B) */ + out: put_page(page); return err; diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 55b080101a20..b304c17d53a3 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -284,7 +284,11 @@ int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, if (desc->affinity_notify) { kref_get(&desc->affinity_notify->kref); - schedule_work(&desc->affinity_notify->work); + if (!schedule_work(&desc->affinity_notify->work)) { + /* Work was already scheduled, drop our extra ref */ + kref_put(&desc->affinity_notify->kref, + desc->affinity_notify->release); + } } irqd_set(data, IRQD_AFFINITY_SET); @@ -384,7 +388,10 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify) raw_spin_unlock_irqrestore(&desc->lock, flags); if (old_notify) { - cancel_work_sync(&old_notify->work); + if (cancel_work_sync(&old_notify->work)) { + /* Pending work had a ref, put that one too */ + kref_put(&old_notify->kref, old_notify->release); + } kref_put(&old_notify->kref, old_notify->release); } diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index a76be87d013d..c44a7db804d1 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -174,7 +174,6 @@ unsigned long kallsyms_lookup_name(const char *name) } return module_kallsyms_lookup_name(name); } -EXPORT_SYMBOL_GPL(kallsyms_lookup_name); int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, unsigned long), @@ -193,7 +192,6 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, } return module_kallsyms_on_each_symbol(fn, data); } -EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol); static unsigned long get_symbol_pos(unsigned long addr, unsigned long *symbolsize, diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 34e28b236d68..2625c241ac00 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -612,6 +612,18 @@ void wait_for_kprobe_optimizer(void) mutex_unlock(&kprobe_mutex); } +static bool optprobe_queued_unopt(struct optimized_kprobe *op) +{ + struct optimized_kprobe *_op; + + list_for_each_entry(_op, &unoptimizing_list, list) { + if (op == _op) + return true; + } + + return false; +} + /* Optimize kprobe if p is ready to be optimized */ static void optimize_kprobe(struct kprobe *p) { @@ -633,17 +645,21 @@ static void optimize_kprobe(struct kprobe *p) return; /* Check if it is already optimized. */ - if (op->kp.flags & KPROBE_FLAG_OPTIMIZED) + if (op->kp.flags & KPROBE_FLAG_OPTIMIZED) { + if (optprobe_queued_unopt(op)) { + /* This is under unoptimizing. Just dequeue the probe */ + list_del_init(&op->list); + } return; + } op->kp.flags |= KPROBE_FLAG_OPTIMIZED; - if (!list_empty(&op->list)) - /* This is under unoptimizing. Just dequeue the probe */ - list_del_init(&op->list); - else { - list_add(&op->list, &optimizing_list); - kick_kprobe_optimizer(); - } + /* On unoptimizing/optimizing_list, op must have OPTIMIZED flag */ + if (WARN_ON_ONCE(!list_empty(&op->list))) + return; + + list_add(&op->list, &optimizing_list); + kick_kprobe_optimizer(); } /* Short cut to direct unoptimizing */ @@ -665,30 +681,33 @@ static void unoptimize_kprobe(struct kprobe *p, bool force) return; /* This is not an optprobe nor optimized */ op = container_of(p, struct optimized_kprobe, kp); - if (!kprobe_optimized(p)) { - /* Unoptimized or unoptimizing case */ - if (force && !list_empty(&op->list)) { - /* - * Only if this is unoptimizing kprobe and forced, - * forcibly unoptimize it. (No need to unoptimize - * unoptimized kprobe again :) - */ + if (!kprobe_optimized(p)) + return; + + if (!list_empty(&op->list)) { + if (optprobe_queued_unopt(op)) { + /* Queued in unoptimizing queue */ + if (force) { + /* + * Forcibly unoptimize the kprobe here, and queue it + * in the freeing list for release afterwards. + */ + force_unoptimize_kprobe(op); + list_move(&op->list, &freeing_list); + } + } else { + /* Dequeue from the optimizing queue */ list_del_init(&op->list); - force_unoptimize_kprobe(op); + op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; } return; } - if (!list_empty(&op->list)) { - /* Dequeue from the optimization queue */ - list_del_init(&op->list); - return; - } /* Optimized kprobe case */ - if (force) + if (force) { /* Forcibly update the code: this is a special case */ force_unoptimize_kprobe(op); - else { + } else { list_add(&op->list, &unoptimizing_list); kick_kprobe_optimizer(); } diff --git a/kernel/notifier.c b/kernel/notifier.c index d9f5081d578d..157d7c29f720 100644 --- a/kernel/notifier.c +++ b/kernel/notifier.c @@ -554,7 +554,7 @@ NOKPROBE_SYMBOL(notify_die); int register_die_notifier(struct notifier_block *nb) { - vmalloc_sync_all(); + vmalloc_sync_mappings(); return atomic_notifier_chain_register(&die_chain, nb); } EXPORT_SYMBOL_GPL(register_die_notifier); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8c3a2d7dcf4e..6c0b7d8d2f1c 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4999,9 +4999,6 @@ recheck: return retval; } - if (pi) - cpuset_read_lock(); - /* * Make sure no PI-waiters arrive (or leave) while we are * changing the priority of the task: @@ -5076,8 +5073,6 @@ change: if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { policy = oldpolicy = -1; task_rq_unlock(rq, p, &rf); - if (pi) - cpuset_read_unlock(); goto recheck; } @@ -5138,10 +5133,8 @@ change: preempt_disable(); task_rq_unlock(rq, p, &rf); - if (pi) { - cpuset_read_unlock(); + if (pi) rt_mutex_adjust_pi(p); - } /* Run balance callbacks after we've adjusted the PI chain: */ balance_callback(rq); @@ -5151,8 +5144,6 @@ change: unlock: task_rq_unlock(rq, p, &rf); - if (pi) - cpuset_read_unlock(); return retval; } @@ -5237,14 +5228,9 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) rcu_read_lock(); retval = -ESRCH; p = find_process_by_pid(pid); - if (likely(p)) - get_task_struct(p); - rcu_read_unlock(); - - if (likely(p)) { + if (p != NULL) retval = sched_setscheduler(p, policy, &lparam); - put_task_struct(p); - } + rcu_read_unlock(); return retval; } diff --git a/kernel/signal.c b/kernel/signal.c index e8aade0d9dca..6cac97119a53 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -414,27 +414,32 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi { struct sigqueue *q = NULL; struct user_struct *user; + int sigpending; /* * Protect access to @t credentials. This can go away when all * callers hold rcu read lock. + * + * NOTE! A pending signal will hold on to the user refcount, + * and we get/put the refcount only when the sigpending count + * changes from/to zero. */ rcu_read_lock(); - user = get_uid(__task_cred(t)->user); - atomic_inc(&user->sigpending); + user = __task_cred(t)->user; + sigpending = atomic_inc_return(&user->sigpending); + if (sigpending == 1) + get_uid(user); rcu_read_unlock(); - if (override_rlimit || - atomic_read(&user->sigpending) <= - task_rlimit(t, RLIMIT_SIGPENDING)) { + if (override_rlimit || likely(sigpending <= task_rlimit(t, RLIMIT_SIGPENDING))) { q = kmem_cache_alloc(sigqueue_cachep, flags); } else { print_dropped_signal(sig); } if (unlikely(q == NULL)) { - atomic_dec(&user->sigpending); - free_uid(user); + if (atomic_dec_and_test(&user->sigpending)) + free_uid(user); } else { INIT_LIST_HEAD(&q->list); q->flags = 0; @@ -448,8 +453,8 @@ static void __sigqueue_free(struct sigqueue *q) { if (q->flags & SIGQUEUE_PREALLOC) return; - atomic_dec(&q->user->sigpending); - free_uid(q->user); + if (atomic_dec_and_test(&q->user->sigpending)) + free_uid(q->user); kmem_cache_free(sigqueue_cachep, q); } diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 4b2ad374167b..e7e483cdbea6 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -1888,8 +1888,11 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, } ret = 0; - if (bt == NULL) + if (bt == NULL) { ret = blk_trace_setup_queue(q, bdev); + bt = rcu_dereference_protected(q->blk_trace, + lockdep_is_held(&q->blk_trace_mutex)); + } if (ret == 0) { if (attr == &dev_attr_act_mask) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 4f1a33b10872..6cf680965682 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -811,6 +811,29 @@ static const char *synth_field_fmt(char *type) return fmt; } +static void print_synth_event_num_val(struct trace_seq *s, + char *print_fmt, char *name, + int size, u64 val, char *space) +{ + switch (size) { + case 1: + trace_seq_printf(s, print_fmt, name, (u8)val, space); + break; + + case 2: + trace_seq_printf(s, print_fmt, name, (u16)val, space); + break; + + case 4: + trace_seq_printf(s, print_fmt, name, (u32)val, space); + break; + + default: + trace_seq_printf(s, print_fmt, name, val, space); + break; + } +} + static enum print_line_t print_synth_event(struct trace_iterator *iter, int flags, struct trace_event *event) @@ -849,10 +872,13 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter, } else { struct trace_print_flags __flags[] = { __def_gfpflag_names, {-1, NULL} }; + char *space = (i == se->n_fields - 1 ? "" : " "); - trace_seq_printf(s, print_fmt, se->fields[i]->name, - entry->fields[n_u64], - i == se->n_fields - 1 ? "" : " "); + print_synth_event_num_val(s, print_fmt, + se->fields[i]->name, + se->fields[i]->size, + entry->fields[n_u64], + space); if (strcmp(se->fields[i]->type, "gfp_t") == 0) { trace_seq_puts(s, " ("); diff --git a/kernel/user.c b/kernel/user.c index a32a8a59a13c..5235d7f49982 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -18,7 +18,6 @@ #include #include #include -#include #include /* @@ -206,7 +205,6 @@ struct user_struct *alloc_uid(kuid_t uid) } spin_unlock_irq(&uidhash_lock); } - proc_register_uid(uid); return up; } @@ -225,7 +223,6 @@ static int __init uid_cache_init(void) spin_lock_irq(&uidhash_lock); uid_hash_insert(&root_user, uidhashentry(GLOBAL_ROOT_UID)); spin_unlock_irq(&uidhash_lock); - proc_register_uid(GLOBAL_ROOT_UID); return 0; } diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 445cc6d1166e..b58be3e0e3e1 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1425,14 +1425,16 @@ static void __queue_work(int cpu, struct workqueue_struct *wq, return; rcu_read_lock(); retry: - if (req_cpu == WORK_CPU_UNBOUND) - cpu = wq_select_unbound_cpu(raw_smp_processor_id()); - /* pwq which will be used unless @work is executing elsewhere */ - if (!(wq->flags & WQ_UNBOUND)) - pwq = per_cpu_ptr(wq->cpu_pwqs, cpu); - else + if (wq->flags & WQ_UNBOUND) { + if (req_cpu == WORK_CPU_UNBOUND) + cpu = wq_select_unbound_cpu(raw_smp_processor_id()); pwq = unbound_pwq_by_node(wq, cpu_to_node(cpu)); + } else { + if (req_cpu == WORK_CPU_UNBOUND) + cpu = raw_smp_processor_id(); + pwq = per_cpu_ptr(wq->cpu_pwqs, cpu); + } /* * If @work was previously on a different pool, it might still be diff --git a/lib/Makefile b/lib/Makefile index 793d3ecf1097..b0a753f92a97 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -87,6 +87,7 @@ obj-$(CONFIG_TEST_KMOD) += test_kmod.o obj-$(CONFIG_TEST_DEBUG_VIRTUAL) += test_debug_virtual.o obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o +CFLAGS_test_stackinit.o += $(call cc-disable-warning, switch-unreachable) obj-$(CONFIG_TEST_STACKINIT) += test_stackinit.o obj-$(CONFIG_TEST_BLACKHOLE_DEV) += test_blackhole_dev.o obj-$(CONFIG_TEST_MEMINIT) += test_meminit.o diff --git a/lib/test_stackinit.c b/lib/test_stackinit.c index 2d7d257a430e..f93b1e145ada 100644 --- a/lib/test_stackinit.c +++ b/lib/test_stackinit.c @@ -92,8 +92,9 @@ static bool range_contains(char *haystack_start, size_t haystack_size, * @var_type: type to be tested for zeroing initialization * @which: is this a SCALAR, STRING, or STRUCT type? * @init_level: what kind of initialization is performed + * @xfail: is this test expected to fail? */ -#define DEFINE_TEST_DRIVER(name, var_type, which) \ +#define DEFINE_TEST_DRIVER(name, var_type, which, xfail) \ /* Returns 0 on success, 1 on failure. */ \ static noinline __init int test_ ## name (void) \ { \ @@ -139,13 +140,14 @@ static noinline __init int test_ ## name (void) \ for (sum = 0, i = 0; i < target_size; i++) \ sum += (check_buf[i] == 0xFF); \ \ - if (sum == 0) \ + if (sum == 0) { \ pr_info(#name " ok\n"); \ - else \ - pr_warn(#name " FAIL (uninit bytes: %d)\n", \ - sum); \ - \ - return (sum != 0); \ + return 0; \ + } else { \ + pr_warn(#name " %sFAIL (uninit bytes: %d)\n", \ + (xfail) ? "X" : "", sum); \ + return (xfail) ? 0 : 1; \ + } \ } #define DEFINE_TEST(name, var_type, which, init_level) \ /* no-op to force compiler into ignoring "uninitialized" vars */\ @@ -189,7 +191,7 @@ static noinline __init int leaf_ ## name(unsigned long sp, \ \ return (int)buf[0] | (int)buf[sizeof(buf) - 1]; \ } \ -DEFINE_TEST_DRIVER(name, var_type, which) +DEFINE_TEST_DRIVER(name, var_type, which, 0) /* Structure with no padding. */ struct test_packed { @@ -326,8 +328,14 @@ static noinline __init int leaf_switch_2_none(unsigned long sp, bool fill, return __leaf_switch_none(2, fill); } -DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR); -DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR); +/* + * These are expected to fail for most configurations because neither + * GCC nor Clang have a way to perform initialization of variables in + * non-code areas (i.e. in a switch statement before the first "case"). + * https://bugs.llvm.org/show_bug.cgi?id=44916 + */ +DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR, 1); +DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, 1); static int __init test_stackinit_init(void) { diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 6c9689281c07..0d96831b6ded 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3032,8 +3032,7 @@ void set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw, return; flush_cache_range(vma, address, address + HPAGE_PMD_SIZE); - pmdval = *pvmw->pmd; - pmdp_invalidate(vma, address, pvmw->pmd); + pmdval = pmdp_invalidate(vma, address, pvmw->pmd); if (pmd_dirty(pmdval)) set_page_dirty(page); entry = make_migration_entry(page, pmd_write(pmdval)); diff --git a/mm/madvise.c b/mm/madvise.c index e5f1cd585e41..360a2d46499e 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -335,12 +335,14 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd, } page = pmd_page(orig_pmd); + + /* Do not interfere with other mappings of this page */ + if (page_mapcount(page) != 1) + goto huge_unlock; + if (next - addr != HPAGE_PMD_SIZE) { int err; - if (page_mapcount(page) != 1) - goto huge_unlock; - get_page(page); spin_unlock(ptl); lock_page(page); @@ -426,6 +428,10 @@ regular_page: continue; } + /* Do not interfere with other mappings of this page */ + if (page_mapcount(page) != 1) + continue; + VM_BUG_ON_PAGE(PageTransCompound(page), page); if (pte_young(ptent)) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index ae9044bc9f80..5d0575d633d2 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -786,6 +786,17 @@ void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val) rcu_read_unlock(); } +void mod_memcg_obj_state(void *p, int idx, int val) +{ + struct mem_cgroup *memcg; + + rcu_read_lock(); + memcg = mem_cgroup_from_obj(p); + if (memcg) + mod_memcg_state(memcg, idx, val); + rcu_read_unlock(); +} + /** * __count_memcg_events - account VM events in a cgroup * @memcg: the memory cgroup @@ -2414,28 +2425,41 @@ static void high_work_func(struct work_struct *work) #define MEMCG_DELAY_SCALING_SHIFT 14 /* - * Scheduled by try_charge() to be executed from the userland return path - * and reclaims memory over the high limit. + * Get the number of jiffies that we should penalise a mischievous cgroup which + * is exceeding its memory.high by checking both it and its ancestors. */ -void mem_cgroup_handle_over_high(void) +static unsigned long calculate_high_delay(struct mem_cgroup *memcg, + unsigned int nr_pages) { - unsigned long usage, high, clamped_high; - unsigned long pflags; - unsigned long penalty_jiffies, overage; - unsigned int nr_pages = current->memcg_nr_pages_over_high; - struct mem_cgroup *memcg; + unsigned long penalty_jiffies; + u64 max_overage = 0; - if (likely(!nr_pages)) - return; + do { + unsigned long usage, high; + u64 overage; - memcg = get_mem_cgroup_from_mm(current->mm); - reclaim_high(memcg, nr_pages, GFP_KERNEL); - current->memcg_nr_pages_over_high = 0; + usage = page_counter_read(&memcg->memory); + high = READ_ONCE(memcg->high); + + /* + * Prevent division by 0 in overage calculation by acting as if + * it was a threshold of 1 page + */ + high = max(high, 1UL); + + overage = usage - high; + overage <<= MEMCG_DELAY_PRECISION_SHIFT; + overage = div64_u64(overage, high); + + if (overage > max_overage) + max_overage = overage; + } while ((memcg = parent_mem_cgroup(memcg)) && + !mem_cgroup_is_root(memcg)); + + if (!max_overage) + return 0; /* - * memory.high is breached and reclaim is unable to keep up. Throttle - * allocators proactively to slow down excessive growth. - * * We use overage compared to memory.high to calculate the number of * jiffies to sleep (penalty_jiffies). Ideally this value should be * fairly lenient on small overages, and increasingly harsh when the @@ -2443,24 +2467,9 @@ void mem_cgroup_handle_over_high(void) * its crazy behaviour, so we exponentially increase the delay based on * overage amount. */ - - usage = page_counter_read(&memcg->memory); - high = READ_ONCE(memcg->high); - - if (usage <= high) - goto out; - - /* - * Prevent division by 0 in overage calculation by acting as if it was a - * threshold of 1 page - */ - clamped_high = max(high, 1UL); - - overage = div_u64((u64)(usage - high) << MEMCG_DELAY_PRECISION_SHIFT, - clamped_high); - - penalty_jiffies = ((u64)overage * overage * HZ) - >> (MEMCG_DELAY_PRECISION_SHIFT + MEMCG_DELAY_SCALING_SHIFT); + penalty_jiffies = max_overage * max_overage * HZ; + penalty_jiffies >>= MEMCG_DELAY_PRECISION_SHIFT; + penalty_jiffies >>= MEMCG_DELAY_SCALING_SHIFT; /* * Factor in the task's own contribution to the overage, such that four @@ -2477,7 +2486,32 @@ void mem_cgroup_handle_over_high(void) * application moving forwards and also permit diagnostics, albeit * extremely slowly. */ - penalty_jiffies = min(penalty_jiffies, MEMCG_MAX_HIGH_DELAY_JIFFIES); + return min(penalty_jiffies, MEMCG_MAX_HIGH_DELAY_JIFFIES); +} + +/* + * Scheduled by try_charge() to be executed from the userland return path + * and reclaims memory over the high limit. + */ +void mem_cgroup_handle_over_high(void) +{ + unsigned long penalty_jiffies; + unsigned long pflags; + unsigned int nr_pages = current->memcg_nr_pages_over_high; + struct mem_cgroup *memcg; + + if (likely(!nr_pages)) + return; + + memcg = get_mem_cgroup_from_mm(current->mm); + reclaim_high(memcg, nr_pages, GFP_KERNEL); + current->memcg_nr_pages_over_high = 0; + + /* + * memory.high is breached and reclaim is unable to keep up. Throttle + * allocators proactively to slow down excessive growth. + */ + penalty_jiffies = calculate_high_delay(memcg, nr_pages); /* * Don't sleep if the amount of jiffies this memcg owes us is so low @@ -2755,6 +2789,33 @@ static void commit_charge(struct page *page, struct mem_cgroup *memcg, } #ifdef CONFIG_MEMCG_KMEM +/* + * Returns a pointer to the memory cgroup to which the kernel object is charged. + * + * The caller must ensure the memcg lifetime, e.g. by taking rcu_read_lock(), + * cgroup_mutex, etc. + */ +struct mem_cgroup *mem_cgroup_from_obj(void *p) +{ + struct page *page; + + if (mem_cgroup_disabled()) + return NULL; + + page = virt_to_head_page(p); + + /* + * Slab pages don't have page->mem_cgroup set because corresponding + * kmem caches can be reparented during the lifetime. That's why + * memcg_from_slab_page() should be used instead. + */ + if (PageSlab(page)) + return memcg_from_slab_page(page); + + /* All other pages use page->mem_cgroup */ + return page->mem_cgroup; +} + static int memcg_alloc_cache_id(void) { int id, size; @@ -4151,7 +4212,7 @@ static void __mem_cgroup_usage_unregister_event(struct mem_cgroup *memcg, struct mem_cgroup_thresholds *thresholds; struct mem_cgroup_threshold_ary *new; unsigned long usage; - int i, j, size; + int i, j, size, entries; mutex_lock(&memcg->thresholds_lock); @@ -4171,14 +4232,20 @@ static void __mem_cgroup_usage_unregister_event(struct mem_cgroup *memcg, __mem_cgroup_threshold(memcg, type == _MEMSWAP); /* Calculate new number of threshold */ - size = 0; + size = entries = 0; for (i = 0; i < thresholds->primary->size; i++) { if (thresholds->primary->entries[i].eventfd != eventfd) size++; + else + entries++; } new = thresholds->spare; + /* If no items related to eventfd have been cleared, nothing to do */ + if (!entries) + goto unlock; + /* Set thresholds array to NULL if we don't have thresholds */ if (!size) { kfree(new); @@ -6792,19 +6859,9 @@ void mem_cgroup_sk_alloc(struct sock *sk) if (!mem_cgroup_sockets_enabled) return; - /* - * Socket cloning can throw us here with sk_memcg already - * filled. It won't however, necessarily happen from - * process context. So the test for root memcg given - * the current task's memcg won't help us in this case. - * - * Respecting the original socket's memcg is a better - * decision in this case. - */ - if (sk->sk_memcg) { - css_get(&sk->sk_memcg->css); + /* Do not associate the sock with unrelated interrupted task's memcg. */ + if (in_interrupt()) return; - } rcu_read_lock(); memcg = mem_cgroup_from_task(current); diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 827f337352f4..c844f2c8ef31 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -598,7 +598,13 @@ EXPORT_SYMBOL_GPL(__online_page_free); static void generic_online_page(struct page *page, unsigned int order) { - kernel_map_pages(page, 1 << order, 1); + /* + * Freeing the page with debug_pagealloc enabled will try to unmap it, + * so we should map it first. This is better than introducing a special + * case in page freeing fast path. + */ + if (debug_pagealloc_enabled_static()) + kernel_map_pages(page, 1 << order, 1); __free_pages_core(page, order); totalram_pages_add(1UL << order); #ifdef CONFIG_HIGHMEM diff --git a/mm/mprotect.c b/mm/mprotect.c index 3cad0a44df91..65d317058e9e 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -161,6 +161,31 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, return pages; } +/* + * Used when setting automatic NUMA hinting protection where it is + * critical that a numa hinting PMD is not confused with a bad PMD. + */ +static inline int pmd_none_or_clear_bad_unless_trans_huge(pmd_t *pmd) +{ + pmd_t pmdval = pmd_read_atomic(pmd); + + /* See pmd_none_or_trans_huge_or_clear_bad for info on barrier */ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + barrier(); +#endif + + if (pmd_none(pmdval)) + return 1; + if (pmd_trans_huge(pmdval)) + return 0; + if (unlikely(pmd_bad(pmdval))) { + pmd_clear_bad(pmd); + return 1; + } + + return 0; +} + static inline unsigned long change_pmd_range(struct vm_area_struct *vma, pud_t *pud, unsigned long addr, unsigned long end, pgprot_t newprot, int dirty_accountable, int prot_numa) @@ -178,8 +203,17 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma, unsigned long this_pages; next = pmd_addr_end(addr, end); - if (!is_swap_pmd(*pmd) && !pmd_trans_huge(*pmd) && !pmd_devmap(*pmd) - && pmd_none_or_clear_bad(pmd)) + + /* + * Automatic NUMA balancing walks the tables with mmap_sem + * held for read. It's possible a parallel update to occur + * between pmd_trans_huge() and a pmd_none_or_clear_bad() + * check leading to a false positive and clearing. + * Hence, it's necessary to atomically read the PMD value + * for all the checks. + */ + if (!is_swap_pmd(*pmd) && !pmd_devmap(*pmd) && + pmd_none_or_clear_bad_unless_trans_huge(pmd)) goto next; /* invoke the mmu notifier if the pmd is populated */ diff --git a/mm/nommu.c b/mm/nommu.c index 99b7ec318824..3b67bd20c2af 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -359,10 +359,14 @@ void vm_unmap_aliases(void) EXPORT_SYMBOL_GPL(vm_unmap_aliases); /* - * Implement a stub for vmalloc_sync_all() if the architecture chose not to - * have one. + * Implement a stub for vmalloc_sync_[un]mapping() if the architecture + * chose not to have one. */ -void __weak vmalloc_sync_all(void) +void __weak vmalloc_sync_mappings(void) +{ +} + +void __weak vmalloc_sync_unmappings(void) { } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index aadbe593a7de..021726afd3c5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -7659,6 +7659,7 @@ unsigned long free_reserved_area(void *start, void *end, int poison, const char return pages; } +EXPORT_SYMBOL_GPL(free_reserved_area); #ifdef CONFIG_HIGHMEM void free_highmem_page(struct page *page) diff --git a/mm/slub.c b/mm/slub.c index c153d1d80bba..ccc3e840b0eb 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1985,8 +1985,6 @@ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node, if (node == NUMA_NO_NODE) searchnode = numa_mem_id(); - else if (!node_present_pages(node)) - searchnode = node_to_mem_node(node); object = get_partial_node(s, get_node(s, searchnode), c, flags); if (object || node != NUMA_NO_NODE) @@ -2575,17 +2573,27 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, struct page *page; page = c->page; - if (!page) + if (!page) { + /* + * if the node is not online or has no normal memory, just + * ignore the node constraint + */ + if (unlikely(node != NUMA_NO_NODE && + !node_state(node, N_NORMAL_MEMORY))) + node = NUMA_NO_NODE; goto new_slab; + } redo: if (unlikely(!node_match(page, node))) { - int searchnode = node; - - if (node != NUMA_NO_NODE && !node_present_pages(node)) - searchnode = node_to_mem_node(node); - - if (unlikely(!node_match(page, searchnode))) { + /* + * same as above but node_match() being false already + * implies node != NUMA_NO_NODE + */ + if (!node_state(node, N_NORMAL_MEMORY)) { + node = NUMA_NO_NODE; + goto redo; + } else { stat(s, ALLOC_NODE_MISMATCH); deactivate_slab(s, page, c->freelist, c); goto new_slab; @@ -3009,11 +3017,13 @@ redo: barrier(); if (likely(page == c->page)) { - set_freepointer(s, tail_obj, c->freelist); + void **freelist = READ_ONCE(c->freelist); + + set_freepointer(s, tail_obj, freelist); if (unlikely(!this_cpu_cmpxchg_double( s->cpu_slab->freelist, s->cpu_slab->tid, - c->freelist, tid, + freelist, tid, head, next_tid(tid)))) { note_cmpxchg_failure("slab_free", s, tid); @@ -3186,6 +3196,15 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size, void *object = c->freelist; if (unlikely(!object)) { + /* + * We may have removed an object from c->freelist using + * the fastpath in the previous iteration; in that case, + * c->tid has not been bumped yet. + * Since ___slab_alloc() may reenable interrupts while + * allocating memory, we should bump c->tid now. + */ + c->tid = next_tid(c->tid); + /* * Invoking slow path likely have side-effect * of re-populating per CPU c->freelist diff --git a/mm/sparse.c b/mm/sparse.c index a5e5c1c3a2a8..78bbecd904c3 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -742,6 +742,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, struct mem_section *ms = __pfn_to_section(pfn); bool section_is_early = early_section(ms); struct page *memmap = NULL; + bool empty; unsigned long *subsection_map = ms->usage ? &ms->usage->subsection_map[0] : NULL; @@ -772,7 +773,8 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, * For 2/ and 3/ the SPARSEMEM_VMEMMAP={y,n} cases are unified */ bitmap_xor(subsection_map, map, subsection_map, SUBSECTIONS_PER_SECTION); - if (bitmap_empty(subsection_map, SUBSECTIONS_PER_SECTION)) { + empty = bitmap_empty(subsection_map, SUBSECTIONS_PER_SECTION); + if (empty) { unsigned long section_nr = pfn_to_section_nr(pfn); /* @@ -787,13 +789,21 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, ms->usage = NULL; } memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr); - ms->section_mem_map = (unsigned long)NULL; + /* + * Mark the section invalid so that valid_section() + * return false. This prevents code from dereferencing + * ms->usage array. + */ + ms->section_mem_map &= ~SECTION_HAS_MEM_MAP; } if (section_is_early && memmap) free_map_bootmem(memmap); else depopulate_section_memmap(pfn, nr_pages, altmap); + + if (empty) + ms->section_mem_map = (unsigned long)NULL; } static struct page * __meminit section_activate(int nid, unsigned long pfn, diff --git a/mm/swapfile.c b/mm/swapfile.c index dab43523afdd..891a3ef48651 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2892,10 +2892,6 @@ static int claim_swapfile(struct swap_info_struct *p, struct inode *inode) p->bdev = inode->i_sb->s_bdev; } - inode_lock(inode); - if (IS_SWAPFILE(inode)) - return -EBUSY; - return 0; } @@ -3150,17 +3146,22 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) mapping = swap_file->f_mapping; inode = mapping->host; - /* If S_ISREG(inode->i_mode) will do inode_lock(inode); */ error = claim_swapfile(p, inode); if (unlikely(error)) goto bad_swap; + inode_lock(inode); + if (IS_SWAPFILE(inode)) { + error = -EBUSY; + goto bad_swap_unlock_inode; + } + /* * Read the swap header. */ if (!mapping->a_ops->readpage) { error = -EINVAL; - goto bad_swap; + goto bad_swap_unlock_inode; } page = read_mapping_page(mapping, 0, swap_file); if (IS_ERR(page)) { @@ -3172,14 +3173,14 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) maxpages = read_swap_header(p, swap_header, inode); if (unlikely(!maxpages)) { error = -EINVAL; - goto bad_swap; + goto bad_swap_unlock_inode; } /* OK, set up the swap map and apply the bad block list */ swap_map = vzalloc(maxpages); if (!swap_map) { error = -ENOMEM; - goto bad_swap; + goto bad_swap_unlock_inode; } if (bdi_cap_stable_pages_required(inode_to_bdi(inode))) @@ -3204,7 +3205,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) GFP_KERNEL); if (!cluster_info) { error = -ENOMEM; - goto bad_swap; + goto bad_swap_unlock_inode; } for (ci = 0; ci < nr_cluster; ci++) @@ -3213,7 +3214,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) p->percpu_cluster = alloc_percpu(struct percpu_cluster); if (!p->percpu_cluster) { error = -ENOMEM; - goto bad_swap; + goto bad_swap_unlock_inode; } for_each_possible_cpu(cpu) { struct percpu_cluster *cluster; @@ -3227,13 +3228,13 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) error = swap_cgroup_swapon(p->type, maxpages); if (error) - goto bad_swap; + goto bad_swap_unlock_inode; nr_extents = setup_swap_map_and_extents(p, swap_header, swap_map, cluster_info, maxpages, &span); if (unlikely(nr_extents < 0)) { error = nr_extents; - goto bad_swap; + goto bad_swap_unlock_inode; } /* frontswap enabled? set up bit-per-page map for frontswap */ if (IS_ENABLED(CONFIG_FRONTSWAP)) @@ -3273,7 +3274,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) error = init_swap_address_space(p->type, maxpages); if (error) - goto bad_swap; + goto bad_swap_unlock_inode; /* * Flush any pending IO and dirty mappings before we start using this @@ -3283,7 +3284,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) error = inode_drain_writes(inode); if (error) { inode->i_flags &= ~S_SWAPFILE; - goto bad_swap; + goto bad_swap_unlock_inode; } mutex_lock(&swapon_mutex); @@ -3308,6 +3309,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) error = 0; goto out; +bad_swap_unlock_inode: + inode_unlock(inode); bad_swap: free_percpu(p->percpu_cluster); p->percpu_cluster = NULL; @@ -3315,6 +3318,7 @@ bad_swap: set_blocksize(p->bdev, p->old_block_size); blkdev_put(p->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); } + inode = NULL; destroy_swap_extents(p); swap_cgroup_swapoff(p->type); spin_lock(&swap_lock); @@ -3326,13 +3330,8 @@ bad_swap: kvfree(frontswap_map); if (inced_nr_rotate_swap) atomic_dec(&nr_rotate_swap); - if (swap_file) { - if (inode) { - inode_unlock(inode); - inode = NULL; - } + if (swap_file) filp_close(swap_file, NULL); - } out: if (page && !IS_ERR(page)) { kunmap(page); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 61bdbaf20cde..7d05834e594c 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1259,7 +1259,7 @@ static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end) * First make sure the mappings are removed from all page-tables * before they are freed. */ - vmalloc_sync_all(); + vmalloc_sync_unmappings(); /* * TODO: to calculate a flush range without looping. @@ -3050,16 +3050,19 @@ int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, EXPORT_SYMBOL(remap_vmalloc_range); /* - * Implement a stub for vmalloc_sync_all() if the architecture chose not to - * have one. + * Implement stubs for vmalloc_sync_[un]mappings () if the architecture chose + * not to have one. * * The purpose of this function is to make sure the vmalloc area * mappings are identical in all page-tables in the system. */ -void __weak vmalloc_sync_all(void) +void __weak vmalloc_sync_mappings(void) { } +void __weak vmalloc_sync_unmappings(void) +{ +} static int f(pte_t *pte, unsigned long addr, void *data) { diff --git a/net/Kconfig b/net/Kconfig index e937f30b3ba7..009fbc5b3640 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -52,6 +52,9 @@ config NET_INGRESS config NET_EGRESS bool +config NET_REDIRECT + bool + config SKB_EXTENSIONS bool diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 5b0b20e6da95..d88a4de02237 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -789,6 +789,10 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface) lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex); + /* interface already disabled by batadv_iv_ogm_iface_disable */ + if (!*ogm_buff) + return; + /* the interface gets activated here to avoid race conditions between * the moment of activating the interface in * hardif_activate_interface() where the originator mac is set and diff --git a/net/bpfilter/main.c b/net/bpfilter/main.c index 77396a098fbe..efea4874743e 100644 --- a/net/bpfilter/main.c +++ b/net/bpfilter/main.c @@ -10,7 +10,7 @@ #include #include "msgfmt.h" -int debug_fd; +FILE *debug_f; static int handle_get_cmd(struct mbox_request *cmd) { @@ -35,9 +35,10 @@ static void loop(void) struct mbox_reply reply; int n; + fprintf(debug_f, "testing the buffer\n"); n = read(0, &req, sizeof(req)); if (n != sizeof(req)) { - dprintf(debug_fd, "invalid request %d\n", n); + fprintf(debug_f, "invalid request %d\n", n); return; } @@ -47,7 +48,7 @@ static void loop(void) n = write(1, &reply, sizeof(reply)); if (n != sizeof(reply)) { - dprintf(debug_fd, "reply failed %d\n", n); + fprintf(debug_f, "reply failed %d\n", n); return; } } @@ -55,9 +56,10 @@ static void loop(void) int main(void) { - debug_fd = open("/dev/kmsg", 00000002); - dprintf(debug_fd, "Started bpfilter\n"); + debug_f = fopen("/dev/kmsg", "w"); + setvbuf(debug_f, 0, _IOLBF, 0); + fprintf(debug_f, "Started bpfilter\n"); loop(); - close(debug_fd); + fclose(debug_f); return 0; } diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index e4cb3db2ee77..3d2e9f944e0f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -3250,12 +3250,16 @@ static struct ceph_msg_data *ceph_msg_data_add(struct ceph_msg *msg) static void ceph_msg_data_destroy(struct ceph_msg_data *data) { - if (data->type == CEPH_MSG_DATA_PAGELIST) + if (data->type == CEPH_MSG_DATA_PAGES && data->own_pages) { + int num_pages = calc_pages_for(data->alignment, data->length); + ceph_release_page_vector(data->pages, num_pages); + } else if (data->type == CEPH_MSG_DATA_PAGELIST) { ceph_pagelist_release(data->pagelist); + } } void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages, - size_t length, size_t alignment) + size_t length, size_t alignment, bool own_pages) { struct ceph_msg_data *data; @@ -3267,6 +3271,7 @@ void ceph_msg_data_add_pages(struct ceph_msg *msg, struct page **pages, data->pages = pages; data->length = length; data->alignment = alignment & ~PAGE_MASK; + data->own_pages = own_pages; msg->data_length += length; } diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index ba45b074a362..2352afa62d1f 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -962,7 +962,7 @@ static void ceph_osdc_msg_data_add(struct ceph_msg *msg, BUG_ON(length > (u64) SIZE_MAX); if (length) ceph_msg_data_add_pages(msg, osd_data->pages, - length, osd_data->alignment); + length, osd_data->alignment, false); } else if (osd_data->type == CEPH_OSD_DATA_TYPE_PAGELIST) { BUG_ON(!length); ceph_msg_data_add_pagelist(msg, osd_data->pagelist); @@ -4436,9 +4436,7 @@ static void handle_watch_notify(struct ceph_osd_client *osdc, CEPH_MSG_DATA_PAGES); *lreq->preply_pages = data->pages; *lreq->preply_len = data->length; - } else { - ceph_release_page_vector(data->pages, - calc_pages_for(0, data->length)); + data->own_pages = false; } } lreq->notify_finish_error = return_code; @@ -5500,9 +5498,6 @@ out_unlock_osdc: return m; } -/* - * TODO: switch to a msg-owned pagelist - */ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr) { struct ceph_msg *m; @@ -5516,7 +5511,6 @@ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr) if (data_len) { struct page **pages; - struct ceph_osd_data osd_data; pages = ceph_alloc_page_vector(calc_pages_for(0, data_len), GFP_NOIO); @@ -5525,9 +5519,7 @@ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr) return NULL; } - ceph_osd_data_pages_init(&osd_data, pages, data_len, 0, false, - false); - ceph_osdc_msg_data_add(m, &osd_data); + ceph_msg_data_add_pages(m, pages, data_len, 0, true); } return m; diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 4e0de14f80bb..2a6e63a8edbe 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -710,6 +710,15 @@ int ceph_pg_poolid_by_name(struct ceph_osdmap *map, const char *name) } EXPORT_SYMBOL(ceph_pg_poolid_by_name); +u64 ceph_pg_pool_flags(struct ceph_osdmap *map, u64 id) +{ + struct ceph_pg_pool_info *pi; + + pi = __lookup_pg_pool(&map->pg_pools, id); + return pi ? pi->flags : 0; +} +EXPORT_SYMBOL(ceph_pg_pool_flags); + static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi) { rb_erase(&pi->node, root); diff --git a/net/core/dev.c b/net/core/dev.c index db8c229e0f4a..931dfdcbabf1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4237,7 +4237,7 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, /* Reinjected packets coming from act_mirred or similar should * not get XDP generic processing. */ - if (skb_is_tc_redirected(skb)) + if (skb_is_redirected(skb)) return XDP_PASS; /* XDP packets must be linear and must have sufficient headroom @@ -4786,7 +4786,7 @@ skip_taps: goto out; } #endif - skb_reset_tc(skb); + skb_reset_redirect(skb); skip_classify: if (pfmemalloc && !skb_pfmemalloc_protocol(skb)) goto drop; diff --git a/net/core/devlink.c b/net/core/devlink.c index 61bc67047f56..4c25f1aa2d37 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -3222,34 +3222,41 @@ devlink_param_value_get_from_info(const struct devlink_param *param, struct genl_info *info, union devlink_param_value *value) { + struct nlattr *param_data; int len; - if (param->type != DEVLINK_PARAM_TYPE_BOOL && - !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) + param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]; + + if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data) return -EINVAL; switch (param->type) { case DEVLINK_PARAM_TYPE_U8: - value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); + if (nla_len(param_data) != sizeof(u8)) + return -EINVAL; + value->vu8 = nla_get_u8(param_data); break; case DEVLINK_PARAM_TYPE_U16: - value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); + if (nla_len(param_data) != sizeof(u16)) + return -EINVAL; + value->vu16 = nla_get_u16(param_data); break; case DEVLINK_PARAM_TYPE_U32: - value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); + if (nla_len(param_data) != sizeof(u32)) + return -EINVAL; + value->vu32 = nla_get_u32(param_data); break; case DEVLINK_PARAM_TYPE_STRING: - len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]), - nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); - if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) || + len = strnlen(nla_data(param_data), nla_len(param_data)); + if (len == nla_len(param_data) || len >= __DEVLINK_PARAM_MAX_STRING_VALUE) return -EINVAL; - strcpy(value->vstr, - nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); + strcpy(value->vstr, nla_data(param_data)); break; case DEVLINK_PARAM_TYPE_BOOL: - value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ? - true : false; + if (param_data && nla_len(param_data)) + return -EINVAL; + value->vbool = nla_get_flag(param_data); break; } return 0; @@ -5797,6 +5804,8 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, + [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 }, + [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 }, [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING }, [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 }, [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 }, diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c index 0642f91c4038..b4c87fe31be2 100644 --- a/net/core/netclassid_cgroup.c +++ b/net/core/netclassid_cgroup.c @@ -53,30 +53,60 @@ static void cgrp_css_free(struct cgroup_subsys_state *css) kfree(css_cls_state(css)); } +/* + * To avoid freezing of sockets creation for tasks with big number of threads + * and opened sockets lets release file_lock every 1000 iterated descriptors. + * New sockets will already have been created with new classid. + */ + +struct update_classid_context { + u32 classid; + unsigned int batch; +}; + +#define UPDATE_CLASSID_BATCH 1000 + static int update_classid_sock(const void *v, struct file *file, unsigned n) { int err; + struct update_classid_context *ctx = (void *)v; struct socket *sock = sock_from_file(file, &err); if (sock) { spin_lock(&cgroup_sk_update_lock); - sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, - (unsigned long)v); + sock_cgroup_set_classid(&sock->sk->sk_cgrp_data, ctx->classid); spin_unlock(&cgroup_sk_update_lock); } + if (--ctx->batch == 0) { + ctx->batch = UPDATE_CLASSID_BATCH; + return n + 1; + } return 0; } +static void update_classid_task(struct task_struct *p, u32 classid) +{ + struct update_classid_context ctx = { + .classid = classid, + .batch = UPDATE_CLASSID_BATCH + }; + unsigned int fd = 0; + + do { + task_lock(p); + fd = iterate_fd(p->files, fd, update_classid_sock, &ctx); + task_unlock(p); + cond_resched(); + } while (fd); +} + static void cgrp_attach(struct cgroup_taskset *tset) { struct cgroup_subsys_state *css; struct task_struct *p; cgroup_taskset_for_each(p, css, tset) { - task_lock(p); - iterate_fd(p->files, 0, update_classid_sock, - (void *)(unsigned long)css_cls_state(css)->classid); - task_unlock(p); + update_classid_task(p, css_cls_state(css)->classid); } } @@ -98,10 +128,7 @@ static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft, css_task_iter_start(css, 0, &it); while ((p = css_task_iter_next(&it))) { - task_lock(p); - iterate_fd(p->files, 0, update_classid_sock, - (void *)(unsigned long)cs->classid); - task_unlock(p); + update_classid_task(p, cs->classid); cond_resched(); } css_task_iter_end(&it); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 48b1e429857c..cb3b565ff5ad 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3362,7 +3362,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) /* skb was 'freed' by stack, so clean few * bits and reuse it */ - skb_reset_tc(skb); + skb_reset_redirect(skb); } while (--burst > 0); goto out; /* Skips xmit_mode M_START_XMIT */ } else if (pkt_dev->xmit_mode == M_QUEUE_XMIT) { diff --git a/net/core/sock.c b/net/core/sock.c index b4d1112174c1..0adf7a9e5a90 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1832,7 +1832,10 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) atomic_set(&newsk->sk_zckey, 0); sock_reset_flag(newsk, SOCK_DONE); - mem_cgroup_sk_alloc(newsk); + + /* sk->sk_memcg will be populated at accept() time */ + newsk->sk_memcg = NULL; + cgroup_sk_alloc(&newsk->sk_cgrp_data); rcu_read_lock(); diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 405397801bb0..8291568b707f 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -233,8 +233,11 @@ static void sock_map_free(struct bpf_map *map) struct bpf_stab *stab = container_of(map, struct bpf_stab, map); int i; + /* After the sync no updates or deletes will be in-flight so it + * is safe to walk map and remove entries without risking a race + * in EEXIST update case. + */ synchronize_rcu(); - raw_spin_lock_bh(&stab->lock); for (i = 0; i < stab->map.max_entries; i++) { struct sock **psk = &stab->sks[i]; struct sock *sk; @@ -248,7 +251,6 @@ static void sock_map_free(struct bpf_map *map) release_sock(sk); } } - raw_spin_unlock_bh(&stab->lock); /* wait for psock readers accessing its map link */ synchronize_rcu(); @@ -863,10 +865,13 @@ static void sock_hash_free(struct bpf_map *map) struct hlist_node *node; int i; + /* After the sync no updates or deletes will be in-flight so it + * is safe to walk map and remove entries without risking a race + * in EEXIST update case. + */ synchronize_rcu(); for (i = 0; i < htab->buckets_num; i++) { bucket = sock_hash_select_bucket(htab, i); - raw_spin_lock_bh(&bucket->lock); hlist_for_each_entry_safe(elem, node, &bucket->head, node) { hlist_del_rcu(&elem->node); lock_sock(elem->sk); @@ -875,7 +880,6 @@ static void sock_hash_free(struct bpf_map *map) rcu_read_unlock(); release_sock(elem->sk); } - raw_spin_unlock_bh(&bucket->lock); } /* wait for psock readers accessing its map link */ diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 12f8c7ee4dd8..bf9947c577b6 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -128,7 +128,9 @@ static inline struct net_device *dsa_master_find_slave(struct net_device *dev, /* port.c */ int dsa_port_set_state(struct dsa_port *dp, u8 state, struct switchdev_trans *trans); +int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy); int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy); +void dsa_port_disable_rt(struct dsa_port *dp); void dsa_port_disable(struct dsa_port *dp); int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br); void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br); diff --git a/net/dsa/port.c b/net/dsa/port.c index 9b54e5a76297..fa023af69bc4 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -63,7 +63,7 @@ static void dsa_port_set_state_now(struct dsa_port *dp, u8 state) pr_err("DSA: failed to set STP state %u (%d)\n", state, err); } -int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy) +int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy) { struct dsa_switch *ds = dp->ds; int port = dp->index; @@ -78,14 +78,31 @@ int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy) if (!dp->bridge_dev) dsa_port_set_state_now(dp, BR_STATE_FORWARDING); + if (dp->pl) + phylink_start(dp->pl); + return 0; } -void dsa_port_disable(struct dsa_port *dp) +int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy) +{ + int err; + + rtnl_lock(); + err = dsa_port_enable_rt(dp, phy); + rtnl_unlock(); + + return err; +} + +void dsa_port_disable_rt(struct dsa_port *dp) { struct dsa_switch *ds = dp->ds; int port = dp->index; + if (dp->pl) + phylink_stop(dp->pl); + if (!dp->bridge_dev) dsa_port_set_state_now(dp, BR_STATE_DISABLED); @@ -93,6 +110,13 @@ void dsa_port_disable(struct dsa_port *dp) ds->ops->port_disable(ds, port); } +void dsa_port_disable(struct dsa_port *dp) +{ + rtnl_lock(); + dsa_port_disable_rt(dp); + rtnl_unlock(); +} + int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) { struct dsa_notifier_bridge_info info = { @@ -615,10 +639,6 @@ static int dsa_port_phylink_register(struct dsa_port *dp) goto err_phy_connect; } - rtnl_lock(); - phylink_start(dp->pl); - rtnl_unlock(); - return 0; err_phy_connect: @@ -629,9 +649,14 @@ err_phy_connect: int dsa_port_link_register_of(struct dsa_port *dp) { struct dsa_switch *ds = dp->ds; + struct device_node *phy_np; - if (!ds->ops->adjust_link) - return dsa_port_phylink_register(dp); + if (!ds->ops->adjust_link) { + phy_np = of_parse_phandle(dp->dn, "phy-handle", 0); + if (of_phy_is_fixed_link(dp->dn) || phy_np) + return dsa_port_phylink_register(dp); + return 0; + } dev_warn(ds->dev, "Using legacy PHYLIB callbacks. Please migrate to PHYLINK!\n"); @@ -646,11 +671,12 @@ void dsa_port_link_unregister_of(struct dsa_port *dp) { struct dsa_switch *ds = dp->ds; - if (!ds->ops->adjust_link) { + if (!ds->ops->adjust_link && dp->pl) { rtnl_lock(); phylink_disconnect_phy(dp->pl); rtnl_unlock(); phylink_destroy(dp->pl); + dp->pl = NULL; return; } diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 028e65f4b5ba..23c2210fa7ec 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -90,12 +90,10 @@ static int dsa_slave_open(struct net_device *dev) goto clear_allmulti; } - err = dsa_port_enable(dp, dev->phydev); + err = dsa_port_enable_rt(dp, dev->phydev); if (err) goto clear_promisc; - phylink_start(dp->pl); - return 0; clear_promisc: @@ -119,9 +117,7 @@ static int dsa_slave_close(struct net_device *dev) cancel_work_sync(&dp->xmit_work); skb_queue_purge(&dp->xmit_queue); - phylink_stop(dp->pl); - - dsa_port_disable(dp); + dsa_port_disable_rt(dp); dev_mc_unsync(master, dev); dev_uc_unsync(master, dev); diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index 9e5a883a9f0c..ebe73848d1cf 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -299,49 +299,6 @@ struct sk_buff *dsa_8021q_xmit(struct sk_buff *skb, struct net_device *netdev, } EXPORT_SYMBOL_GPL(dsa_8021q_xmit); -/* In the DSA packet_type handler, skb->data points in the middle of the VLAN - * tag, after tpid and before tci. This is because so far, ETH_HLEN - * (DMAC, SMAC, EtherType) bytes were pulled. - * There are 2 bytes of VLAN tag left in skb->data, and upper - * layers expect the 'real' EtherType to be consumed as well. - * Coincidentally, a VLAN header is also of the same size as - * the number of bytes that need to be pulled. - * - * skb_mac_header skb->data - * | | - * v v - * | | | | | | | | | | | | | | | | | | | - * +-----------------------+-----------------------+-------+-------+-------+ - * | Destination MAC | Source MAC | TPID | TCI | EType | - * +-----------------------+-----------------------+-------+-------+-------+ - * ^ | | - * |<--VLAN_HLEN-->to <---VLAN_HLEN---> - * from | - * >>>>>>> v - * >>>>>>> | | | | | | | | | | | | | | | - * >>>>>>> +-----------------------+-----------------------+-------+ - * >>>>>>> | Destination MAC | Source MAC | EType | - * +-----------------------+-----------------------+-------+ - * ^ ^ - * (now part of | | - * skb->head) skb_mac_header skb->data - */ -struct sk_buff *dsa_8021q_remove_header(struct sk_buff *skb) -{ - u8 *from = skb_mac_header(skb); - u8 *dest = from + VLAN_HLEN; - - memmove(dest, from, ETH_HLEN - VLAN_HLEN); - skb_pull(skb, VLAN_HLEN); - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - skb_reset_mac_len(skb); - skb_pull_rcsum(skb, ETH_HLEN); - - return skb; -} -EXPORT_SYMBOL_GPL(dsa_8021q_remove_header); - static const struct dsa_device_ops dsa_8021q_netdev_ops = { .name = "8021q", .proto = DSA_TAG_PROTO_8021Q, diff --git a/net/dsa/tag_brcm.c b/net/dsa/tag_brcm.c index 9c3114179690..9169b63a89e3 100644 --- a/net/dsa/tag_brcm.c +++ b/net/dsa/tag_brcm.c @@ -140,6 +140,8 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb, /* Remove Broadcom tag and update checksum */ skb_pull_rcsum(skb, BRCM_TAG_LEN); + skb->offload_fwd_mark = 1; + return skb; } #endif diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index 63ef2a14c934..12f3ce52e62e 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -238,14 +238,14 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, { struct sja1105_meta meta = {0}; int source_port, switch_id; - struct vlan_ethhdr *hdr; + struct ethhdr *hdr; u16 tpid, vid, tci; bool is_link_local; bool is_tagged; bool is_meta; - hdr = vlan_eth_hdr(skb); - tpid = ntohs(hdr->h_vlan_proto); + hdr = eth_hdr(skb); + tpid = ntohs(hdr->h_proto); is_tagged = (tpid == ETH_P_SJA1105); is_link_local = sja1105_is_link_local(skb); is_meta = sja1105_is_meta_frame(skb); @@ -254,7 +254,12 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, if (is_tagged) { /* Normal traffic path. */ - tci = ntohs(hdr->h_vlan_TCI); + skb_push_rcsum(skb, ETH_HLEN); + __skb_vlan_pop(skb, &tci); + skb_pull_rcsum(skb, ETH_HLEN); + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + vid = tci & VLAN_VID_MASK; source_port = dsa_8021q_rx_source_port(vid); switch_id = dsa_8021q_rx_switch_id(vid); @@ -283,12 +288,6 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, return NULL; } - /* Delete/overwrite fake VLAN header, DSA expects to not find - * it there, see dsa_switch_rcv: skb_push(skb, ETH_HLEN). - */ - if (is_tagged) - skb = dsa_8021q_remove_header(skb); - return sja1105_rcv_meta_state_machine(skb, &meta, is_link_local, is_meta); } diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 27dc65d7de67..002f341f3564 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -482,12 +482,9 @@ int hsr_get_node_data(struct hsr_priv *hsr, struct hsr_port *port; unsigned long tdiff; - rcu_read_lock(); node = find_node_by_addr_A(&hsr->node_db, addr); - if (!node) { - rcu_read_unlock(); - return -ENOENT; /* No such entry */ - } + if (!node) + return -ENOENT; ether_addr_copy(addr_b, node->macaddress_B); @@ -522,7 +519,5 @@ int hsr_get_node_data(struct hsr_priv *hsr, *addr_b_ifindex = -1; } - rcu_read_unlock(); - return 0; } diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index 8dc0547f01d0..fae21c863b1f 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c @@ -251,15 +251,16 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) if (!na) goto invalid; - hsr_dev = __dev_get_by_index(genl_info_net(info), - nla_get_u32(info->attrs[HSR_A_IFINDEX])); + rcu_read_lock(); + hsr_dev = dev_get_by_index_rcu(genl_info_net(info), + nla_get_u32(info->attrs[HSR_A_IFINDEX])); if (!hsr_dev) - goto invalid; + goto rcu_unlock; if (!is_hsr_master(hsr_dev)) - goto invalid; + goto rcu_unlock; /* Send reply */ - skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb_out) { res = -ENOMEM; goto fail; @@ -313,12 +314,10 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq); if (res < 0) goto nla_put_failure; - rcu_read_lock(); port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); if (port) res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX, port->dev->ifindex); - rcu_read_unlock(); if (res < 0) goto nla_put_failure; @@ -328,20 +327,22 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq); if (res < 0) goto nla_put_failure; - rcu_read_lock(); port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); if (port) res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX, port->dev->ifindex); - rcu_read_unlock(); if (res < 0) goto nla_put_failure; + rcu_read_unlock(); + genlmsg_end(skb_out, msg_head); genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid); return 0; +rcu_unlock: + rcu_read_unlock(); invalid: netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL, NULL); return 0; @@ -351,6 +352,7 @@ nla_put_failure: /* Fall through */ fail: + rcu_read_unlock(); return res; } @@ -358,16 +360,14 @@ fail: */ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) { - /* For receiving */ - struct nlattr *na; - struct net_device *hsr_dev; - - /* For sending */ - struct sk_buff *skb_out; - void *msg_head; - struct hsr_priv *hsr; - void *pos; unsigned char addr[ETH_ALEN]; + struct net_device *hsr_dev; + struct sk_buff *skb_out; + struct hsr_priv *hsr; + bool restart = false; + struct nlattr *na; + void *pos = NULL; + void *msg_head; int res; if (!info) @@ -377,15 +377,17 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) if (!na) goto invalid; - hsr_dev = __dev_get_by_index(genl_info_net(info), - nla_get_u32(info->attrs[HSR_A_IFINDEX])); + rcu_read_lock(); + hsr_dev = dev_get_by_index_rcu(genl_info_net(info), + nla_get_u32(info->attrs[HSR_A_IFINDEX])); if (!hsr_dev) - goto invalid; + goto rcu_unlock; if (!is_hsr_master(hsr_dev)) - goto invalid; + goto rcu_unlock; +restart: /* Send reply */ - skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb_out = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!skb_out) { res = -ENOMEM; goto fail; @@ -399,18 +401,26 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) goto nla_put_failure; } - res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex); - if (res < 0) - goto nla_put_failure; + if (!restart) { + res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex); + if (res < 0) + goto nla_put_failure; + } hsr = netdev_priv(hsr_dev); - rcu_read_lock(); - pos = hsr_get_next_node(hsr, NULL, addr); + if (!pos) + pos = hsr_get_next_node(hsr, NULL, addr); while (pos) { res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr); if (res < 0) { - rcu_read_unlock(); + if (res == -EMSGSIZE) { + genlmsg_end(skb_out, msg_head); + genlmsg_unicast(genl_info_net(info), skb_out, + info->snd_portid); + restart = true; + goto restart; + } goto nla_put_failure; } pos = hsr_get_next_node(hsr, pos, addr); @@ -422,15 +432,18 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) return 0; +rcu_unlock: + rcu_read_unlock(); invalid: netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL, NULL); return 0; nla_put_failure: - kfree_skb(skb_out); + nlmsg_free(skb_out); /* Fall through */ fail: + rcu_read_unlock(); return res; } @@ -457,6 +470,7 @@ static struct genl_family hsr_genl_family __ro_after_init = { .version = 1, .maxattr = HSR_A_MAX, .policy = hsr_genl_policy, + .netnsok = true, .module = THIS_MODULE, .ops = hsr_ops, .n_ops = ARRAY_SIZE(hsr_ops), diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c index fbfd0db182b7..a9104d42aafb 100644 --- a/net/hsr/hsr_slave.c +++ b/net/hsr/hsr_slave.c @@ -145,16 +145,16 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev, if (!port) return -ENOMEM; + port->hsr = hsr; + port->dev = dev; + port->type = type; + if (type != HSR_PT_MASTER) { res = hsr_portdev_setup(dev, port); if (res) goto fail_dev_setup; } - port->hsr = hsr; - port->dev = dev; - port->type = type; - list_add_tail_rcu(&port->port_list, &hsr->ports); synchronize_rcu(); diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index 2c7a38d76a3a..0672b2f01586 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c @@ -21,7 +21,13 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { [IEEE802154_ATTR_HW_ADDR] = { .type = NLA_HW_ADDR, }, [IEEE802154_ATTR_PAN_ID] = { .type = NLA_U16, }, [IEEE802154_ATTR_CHANNEL] = { .type = NLA_U8, }, + [IEEE802154_ATTR_BCN_ORD] = { .type = NLA_U8, }, + [IEEE802154_ATTR_SF_ORD] = { .type = NLA_U8, }, + [IEEE802154_ATTR_PAN_COORD] = { .type = NLA_U8, }, + [IEEE802154_ATTR_BAT_EXT] = { .type = NLA_U8, }, + [IEEE802154_ATTR_COORD_REALIGN] = { .type = NLA_U8, }, [IEEE802154_ATTR_PAGE] = { .type = NLA_U8, }, + [IEEE802154_ATTR_DEV_TYPE] = { .type = NLA_U8, }, [IEEE802154_ATTR_COORD_SHORT_ADDR] = { .type = NLA_U16, }, [IEEE802154_ATTR_COORD_HW_ADDR] = { .type = NLA_HW_ADDR, }, [IEEE802154_ATTR_COORD_PAN_ID] = { .type = NLA_U16, }, diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 03381f3e12ba..a926de2e42b5 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -303,6 +303,7 @@ config SYN_COOKIES config NET_IPVTI tristate "Virtual (secure) IP: tunneling" + depends on IPV6 || IPV6=n select INET_TUNNEL select NET_IP_TUNNEL select XFRM diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 376882215919..0bd10a1f477f 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1724,6 +1724,7 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) { unsigned char optbuf[sizeof(struct ip_options) + 40]; struct ip_options *opt = (struct ip_options *)optbuf; + int res; if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES) return; @@ -1735,7 +1736,11 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) memset(opt, 0, sizeof(struct ip_options)); opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr); - if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL)) + rcu_read_lock(); + res = __ip_options_compile(dev_net(skb->dev), opt, skb, NULL); + rcu_read_unlock(); + + if (res) return; if (gateway) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 71c78d223dfd..48bf3b9be475 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1007,7 +1007,9 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) return -ENOENT; } + rcu_read_lock(); err = fib_table_dump(tb, skb, cb, &filter); + rcu_read_unlock(); return skb->len ? : err; } diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index 5fd6e8ed02b5..66fdbfe5447c 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c @@ -56,7 +56,9 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version) } EXPORT_SYMBOL_GPL(gre_del_protocol); -/* Fills in tpi and returns header length to be pulled. */ +/* Fills in tpi and returns header length to be pulled. + * Note that caller must use pskb_may_pull() before pulling GRE header. + */ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, bool *csum_err, __be16 proto, int nhs) { @@ -110,8 +112,14 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header */ if (greh->flags == 0 && tpi->proto == htons(ETH_P_WCCP)) { + u8 _val, *val; + + val = skb_header_pointer(skb, nhs + hdr_len, + sizeof(_val), &_val); + if (!val) + return -EINVAL; tpi->proto = proto; - if ((*(u8 *)options & 0xF0) != 0x40) + if ((*val & 0xF0) != 0x40) hdr_len += 4; } tpi->hdr_len = hdr_len; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index ac05e273bc66..b0010c710802 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -482,8 +482,28 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern) } spin_unlock_bh(&queue->fastopenq.lock); } + out: release_sock(sk); + if (newsk && mem_cgroup_sockets_enabled) { + int amt; + + /* atomically get the memory usage, set and charge the + * newsk->sk_memcg. + */ + lock_sock(newsk); + + /* The socket has not been accepted yet, no need to look at + * newsk->sk_wmem_queued. + */ + amt = sk_mem_pages(newsk->sk_forward_alloc + + atomic_read(&newsk->sk_rmem_alloc)); + mem_cgroup_sk_alloc(newsk); + if (newsk->sk_memcg && amt) + mem_cgroup_charge_skmem(newsk->sk_memcg, amt); + + release_sock(newsk); + } if (req) reqsk_put(req); return newsk; diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 6a4c82f96e78..5b68bdaa8bff 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -100,13 +100,9 @@ static size_t inet_sk_attr_size(struct sock *sk, aux = handler->idiag_get_aux_size(sk, net_admin); return nla_total_size(sizeof(struct tcp_info)) - + nla_total_size(1) /* INET_DIAG_SHUTDOWN */ - + nla_total_size(1) /* INET_DIAG_TOS */ - + nla_total_size(1) /* INET_DIAG_TCLASS */ - + nla_total_size(4) /* INET_DIAG_MARK */ - + nla_total_size(4) /* INET_DIAG_CLASS_ID */ - + nla_total_size(sizeof(struct inet_diag_meminfo)) + nla_total_size(sizeof(struct inet_diag_msg)) + + inet_diag_msg_attrs_size() + + nla_total_size(sizeof(struct inet_diag_meminfo)) + nla_total_size(SK_MEMINFO_VARS * sizeof(u32)) + nla_total_size(TCP_CA_NAME_MAX) + nla_total_size(sizeof(struct tcpvegas_info)) @@ -147,6 +143,24 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark)) goto errout; + if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) || + ext & (1 << (INET_DIAG_TCLASS - 1))) { + u32 classid = 0; + +#ifdef CONFIG_SOCK_CGROUP_DATA + classid = sock_cgroup_classid(&sk->sk_cgrp_data); +#endif + /* Fallback to socket priority if class id isn't set. + * Classful qdiscs use it as direct reference to class. + * For cgroup2 classid is always zero. + */ + if (!classid) + classid = sk->sk_priority; + + if (nla_put_u32(skb, INET_DIAG_CLASS_ID, classid)) + goto errout; + } + r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); r->idiag_inode = sock_i_ino(sk); @@ -284,24 +298,6 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, goto errout; } - if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) || - ext & (1 << (INET_DIAG_TCLASS - 1))) { - u32 classid = 0; - -#ifdef CONFIG_SOCK_CGROUP_DATA - classid = sock_cgroup_classid(&sk->sk_cgrp_data); -#endif - /* Fallback to socket priority if class id isn't set. - * Classful qdiscs use it as direct reference to class. - * For cgroup2 classid is always zero. - */ - if (!classid) - classid = sk->sk_priority; - - if (nla_put_u32(skb, INET_DIAG_CLASS_ID, classid)) - goto errout; - } - out: nlmsg_end(skb, nlh); return 0; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 10636fb6093e..85ba1453ba5c 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1149,6 +1149,24 @@ static int ipgre_netlink_parms(struct net_device *dev, if (data[IFLA_GRE_FWMARK]) *fwmark = nla_get_u32(data[IFLA_GRE_FWMARK]); + return 0; +} + +static int erspan_netlink_parms(struct net_device *dev, + struct nlattr *data[], + struct nlattr *tb[], + struct ip_tunnel_parm *parms, + __u32 *fwmark) +{ + struct ip_tunnel *t = netdev_priv(dev); + int err; + + err = ipgre_netlink_parms(dev, data, tb, parms, fwmark); + if (err) + return err; + if (!data) + return 0; + if (data[IFLA_GRE_ERSPAN_VER]) { t->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]); @@ -1272,45 +1290,70 @@ static void ipgre_tap_setup(struct net_device *dev) ip_tunnel_setup(dev, gre_tap_net_id); } -static int ipgre_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], - struct netlink_ext_ack *extack) +static int +ipgre_newlink_encap_setup(struct net_device *dev, struct nlattr *data[]) { - struct ip_tunnel_parm p; struct ip_tunnel_encap ipencap; - __u32 fwmark = 0; - int err; if (ipgre_netlink_encap_parms(data, &ipencap)) { struct ip_tunnel *t = netdev_priv(dev); - err = ip_tunnel_encap_setup(t, &ipencap); + int err = ip_tunnel_encap_setup(t, &ipencap); if (err < 0) return err; } + return 0; +} + +static int ipgre_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +{ + struct ip_tunnel_parm p; + __u32 fwmark = 0; + int err; + + err = ipgre_newlink_encap_setup(dev, data); + if (err) + return err; + err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); if (err < 0) return err; return ip_tunnel_newlink(dev, tb, &p, fwmark); } +static int erspan_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +{ + struct ip_tunnel_parm p; + __u32 fwmark = 0; + int err; + + err = ipgre_newlink_encap_setup(dev, data); + if (err) + return err; + + err = erspan_netlink_parms(dev, data, tb, &p, &fwmark); + if (err) + return err; + return ip_tunnel_newlink(dev, tb, &p, fwmark); +} + static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { struct ip_tunnel *t = netdev_priv(dev); - struct ip_tunnel_encap ipencap; __u32 fwmark = t->fwmark; struct ip_tunnel_parm p; int err; - if (ipgre_netlink_encap_parms(data, &ipencap)) { - err = ip_tunnel_encap_setup(t, &ipencap); - - if (err < 0) - return err; - } + err = ipgre_newlink_encap_setup(dev, data); + if (err) + return err; err = ipgre_netlink_parms(dev, data, tb, &p, &fwmark); if (err < 0) @@ -1323,8 +1366,34 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], t->parms.i_flags = p.i_flags; t->parms.o_flags = p.o_flags; - if (strcmp(dev->rtnl_link_ops->kind, "erspan")) - ipgre_link_update(dev, !tb[IFLA_MTU]); + ipgre_link_update(dev, !tb[IFLA_MTU]); + + return 0; +} + +static int erspan_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +{ + struct ip_tunnel *t = netdev_priv(dev); + __u32 fwmark = t->fwmark; + struct ip_tunnel_parm p; + int err; + + err = ipgre_newlink_encap_setup(dev, data); + if (err) + return err; + + err = erspan_netlink_parms(dev, data, tb, &p, &fwmark); + if (err < 0) + return err; + + err = ip_tunnel_changelink(dev, tb, &p, fwmark); + if (err < 0) + return err; + + t->parms.i_flags = p.i_flags; + t->parms.o_flags = p.o_flags; return 0; } @@ -1515,8 +1584,8 @@ static struct rtnl_link_ops erspan_link_ops __read_mostly = { .priv_size = sizeof(struct ip_tunnel), .setup = erspan_setup, .validate = erspan_validate, - .newlink = ipgre_newlink, - .changelink = ipgre_changelink, + .newlink = erspan_newlink, + .changelink = erspan_changelink, .dellink = ip_tunnel_dellink, .get_size = ipgre_get_size, .fill_info = ipgre_fill_info, diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 79eef5db336a..8ecaf0f26973 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -187,17 +187,39 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, int mtu; if (!dst) { - struct rtable *rt; + switch (skb->protocol) { + case htons(ETH_P_IP): { + struct rtable *rt; - fl->u.ip4.flowi4_oif = dev->ifindex; - fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; - rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); - if (IS_ERR(rt)) { + fl->u.ip4.flowi4_oif = dev->ifindex; + fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; + rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); + if (IS_ERR(rt)) { + dev->stats.tx_carrier_errors++; + goto tx_error_icmp; + } + dst = &rt->dst; + skb_dst_set(skb, dst); + break; + } +#if IS_ENABLED(CONFIG_IPV6) + case htons(ETH_P_IPV6): + fl->u.ip6.flowi6_oif = dev->ifindex; + fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; + dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); + if (dst->error) { + dst_release(dst); + dst = NULL; + dev->stats.tx_carrier_errors++; + goto tx_error_icmp; + } + skb_dst_set(skb, dst); + break; +#endif + default: dev->stats.tx_carrier_errors++; goto tx_error_icmp; } - dst = &rt->dst; - skb_dst_set(skb, dst); } dst_hold(dst); diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c index e35736b99300..a93e7d1e1251 100644 --- a/net/ipv4/raw_diag.c +++ b/net/ipv4/raw_diag.c @@ -100,8 +100,9 @@ static int raw_diag_dump_one(struct sk_buff *in_skb, if (IS_ERR(sk)) return PTR_ERR(sk); - rep = nlmsg_new(sizeof(struct inet_diag_msg) + - sizeof(struct inet_diag_meminfo) + 64, + rep = nlmsg_new(nla_total_size(sizeof(struct inet_diag_msg)) + + inet_diag_msg_attrs_size() + + nla_total_size(sizeof(struct inet_diag_meminfo)) + 64, GFP_KERNEL); if (!rep) { sock_put(sk); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index a80d5d49c2a0..8c3e3875abac 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2942,8 +2942,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, err = -EPERM; else if (tp->repair_queue == TCP_SEND_QUEUE) WRITE_ONCE(tp->write_seq, val); - else if (tp->repair_queue == TCP_RECV_QUEUE) + else if (tp->repair_queue == TCP_RECV_QUEUE) { WRITE_ONCE(tp->rcv_nxt, val); + WRITE_ONCE(tp->copied_seq, val); + } else err = -EINVAL; break; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 660b24fe041e..c8d03c1b4c6b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1048,6 +1048,10 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, if (unlikely(!skb)) return -ENOBUFS; + /* retransmit skbs might have a non zero value in skb->dev + * because skb->dev is aliased with skb->rbnode.rb_left + */ + skb->dev = NULL; } inet = inet_sk(sk); @@ -2976,8 +2980,12 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) tcp_skb_tsorted_save(skb) { nskb = __pskb_copy(skb, MAX_TCP_HEADER, GFP_ATOMIC); - err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : - -ENOBUFS; + if (nskb) { + nskb->dev = NULL; + err = tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC); + } else { + err = -ENOBUFS; + } } tcp_skb_tsorted_restore(skb); if (!err) { diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 910555a4d9fe..dccd2286bc28 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c @@ -64,8 +64,9 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, goto out; err = -ENOMEM; - rep = nlmsg_new(sizeof(struct inet_diag_msg) + - sizeof(struct inet_diag_meminfo) + 64, + rep = nlmsg_new(nla_total_size(sizeof(struct inet_diag_msg)) + + inet_diag_msg_attrs_size() + + nla_total_size(sizeof(struct inet_diag_meminfo)) + 64, GFP_KERNEL); if (!rep) goto out; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4a08d3d6eba7..2166e0206ed3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1228,11 +1228,13 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires) } static void -cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, bool del_rt) +cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long expires, + bool del_rt, bool del_peer) { struct fib6_info *f6i; - f6i = addrconf_get_prefix_route(&ifp->addr, ifp->prefix_len, + f6i = addrconf_get_prefix_route(del_peer ? &ifp->peer_addr : &ifp->addr, + ifp->prefix_len, ifp->idev->dev, 0, RTF_DEFAULT, true); if (f6i) { if (del_rt) @@ -1295,7 +1297,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) if (action != CLEANUP_PREFIX_RT_NOP) { cleanup_prefix_route(ifp, expires, - action == CLEANUP_PREFIX_RT_DEL); + action == CLEANUP_PREFIX_RT_DEL, false); } /* clean up prefsrc entries */ @@ -3367,6 +3369,10 @@ static void addrconf_dev_config(struct net_device *dev) (dev->type != ARPHRD_NONE) && (dev->type != ARPHRD_RAWIP)) { /* Alas, we support only Ethernet autoconfiguration. */ + idev = __in6_dev_get(dev); + if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP && + dev->flags & IFF_MULTICAST) + ipv6_mc_up(idev); return; } @@ -4608,12 +4614,14 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, } static int modify_prefix_route(struct inet6_ifaddr *ifp, - unsigned long expires, u32 flags) + unsigned long expires, u32 flags, + bool modify_peer) { struct fib6_info *f6i; u32 prio; - f6i = addrconf_get_prefix_route(&ifp->addr, ifp->prefix_len, + f6i = addrconf_get_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr, + ifp->prefix_len, ifp->idev->dev, 0, RTF_DEFAULT, true); if (!f6i) return -ENOENT; @@ -4624,7 +4632,8 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp, ip6_del_rt(dev_net(ifp->idev->dev), f6i); /* add new one */ - addrconf_prefix_route(&ifp->addr, ifp->prefix_len, + addrconf_prefix_route(modify_peer ? &ifp->peer_addr : &ifp->addr, + ifp->prefix_len, ifp->rt_priority, ifp->idev->dev, expires, flags, GFP_KERNEL); } else { @@ -4646,6 +4655,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg) unsigned long timeout; bool was_managetempaddr; bool had_prefixroute; + bool new_peer = false; ASSERT_RTNL(); @@ -4677,6 +4687,13 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg) cfg->preferred_lft = timeout; } + if (cfg->peer_pfx && + memcmp(&ifp->peer_addr, cfg->peer_pfx, sizeof(struct in6_addr))) { + if (!ipv6_addr_any(&ifp->peer_addr)) + cleanup_prefix_route(ifp, expires, true, true); + new_peer = true; + } + spin_lock_bh(&ifp->lock); was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR; had_prefixroute = ifp->flags & IFA_F_PERMANENT && @@ -4692,6 +4709,9 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg) if (cfg->rt_priority && cfg->rt_priority != ifp->rt_priority) ifp->rt_priority = cfg->rt_priority; + if (new_peer) + ifp->peer_addr = *cfg->peer_pfx; + spin_unlock_bh(&ifp->lock); if (!(ifp->flags&IFA_F_TENTATIVE)) ipv6_ifa_notify(0, ifp); @@ -4700,7 +4720,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg) int rc = -ENOENT; if (had_prefixroute) - rc = modify_prefix_route(ifp, expires, flags); + rc = modify_prefix_route(ifp, expires, flags, false); /* prefix route could have been deleted; if so restore it */ if (rc == -ENOENT) { @@ -4708,6 +4728,15 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg) ifp->rt_priority, ifp->idev->dev, expires, flags, GFP_KERNEL); } + + if (had_prefixroute && !ipv6_addr_any(&ifp->peer_addr)) + rc = modify_prefix_route(ifp, expires, flags, true); + + if (rc == -ENOENT && !ipv6_addr_any(&ifp->peer_addr)) { + addrconf_prefix_route(&ifp->peer_addr, ifp->prefix_len, + ifp->rt_priority, ifp->idev->dev, + expires, flags, GFP_KERNEL); + } } else if (had_prefixroute) { enum cleanup_prefix_rt_t action; unsigned long rt_expires; @@ -4718,7 +4747,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, struct ifa6_config *cfg) if (action != CLEANUP_PREFIX_RT_NOP) { cleanup_prefix_route(ifp, rt_expires, - action == CLEANUP_PREFIX_RT_DEL); + action == CLEANUP_PREFIX_RT_DEL, false); } } @@ -6006,9 +6035,9 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); if (!ipv6_addr_any(&ifp->peer_addr)) - addrconf_prefix_route(&ifp->peer_addr, 128, 0, - ifp->idev->dev, 0, 0, - GFP_ATOMIC); + addrconf_prefix_route(&ifp->peer_addr, 128, + ifp->rt_priority, ifp->idev->dev, + 0, 0, GFP_ATOMIC); break; case RTM_DELADDR: if (ifp->idev->cnf.forwarding) diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 524006aa0d78..cc6180e08a4f 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -311,7 +311,7 @@ static int vti6_rcv(struct sk_buff *skb) if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { rcu_read_unlock(); - return 0; + goto discard; } ipv6h = ipv6_hdr(skb); @@ -450,15 +450,33 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) int mtu; if (!dst) { - fl->u.ip6.flowi6_oif = dev->ifindex; - fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; - dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); - if (dst->error) { - dst_release(dst); - dst = NULL; + switch (skb->protocol) { + case htons(ETH_P_IP): { + struct rtable *rt; + + fl->u.ip4.flowi4_oif = dev->ifindex; + fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; + rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); + if (IS_ERR(rt)) + goto tx_err_link_failure; + dst = &rt->dst; + skb_dst_set(skb, dst); + break; + } + case htons(ETH_P_IPV6): + fl->u.ip6.flowi6_oif = dev->ifindex; + fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; + dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); + if (dst->error) { + dst_release(dst); + dst = NULL; + goto tx_err_link_failure; + } + skb_dst_set(skb, dst); + break; + default: goto tx_err_link_failure; } - skb_dst_set(skb, dst); } dst_hold(dst); diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 79fc012dd2ca..debdaeba5d8c 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -183,9 +183,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, retv = -EBUSY; break; } - } else if (sk->sk_protocol != IPPROTO_TCP) + } else if (sk->sk_protocol == IPPROTO_TCP) { + if (sk->sk_prot != &tcpv6_prot) { + retv = -EBUSY; + break; + } break; - + } else { + break; + } if (sk->sk_state != TCP_ESTABLISHED) { retv = -ENOTCONN; break; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 53caf59c591e..945ef37eab9d 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -197,6 +197,7 @@ static inline int ndisc_is_useropt(const struct net_device *dev, return opt->nd_opt_type == ND_OPT_RDNSS || opt->nd_opt_type == ND_OPT_DNSSL || opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL || + opt->nd_opt_type == ND_OPT_PREF64 || ndisc_ops_is_useropt(dev, opt->nd_opt_type); } diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c8ad20c28c43..70ea4cc126d1 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -5,7 +5,7 @@ * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright (C) 2018 - 2020 Intel Corporation */ #include @@ -78,6 +78,7 @@ static const char * const sta_flag_names[] = { FLAG(MPSP_OWNER), FLAG(MPSP_RECIPIENT), FLAG(PS_DELIVER), + FLAG(USES_ENCRYPTION), #undef FLAG }; diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 0f889b919b06..efc1acc6543c 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -6,7 +6,7 @@ * Copyright 2007-2008 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2015-2017 Intel Deutschland GmbH - * Copyright 2018-2019 Intel Corporation + * Copyright 2018-2020 Intel Corporation */ #include @@ -262,22 +262,29 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) sta ? sta->sta.addr : bcast_addr, ret); } -int ieee80211_set_tx_key(struct ieee80211_key *key) +static int _ieee80211_set_tx_key(struct ieee80211_key *key, bool force) { struct sta_info *sta = key->sta; struct ieee80211_local *local = key->local; assert_key_lock(local); + set_sta_flag(sta, WLAN_STA_USES_ENCRYPTION); + sta->ptk_idx = key->conf.keyidx; - if (!ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT)) + if (force || !ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT)) clear_sta_flag(sta, WLAN_STA_BLOCK_BA); ieee80211_check_fast_xmit(sta); return 0; } +int ieee80211_set_tx_key(struct ieee80211_key *key) +{ + return _ieee80211_set_tx_key(key, false); +} + static void ieee80211_pairwise_rekey(struct ieee80211_key *old, struct ieee80211_key *new) { @@ -441,11 +448,8 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, if (pairwise) { rcu_assign_pointer(sta->ptk[idx], new); if (new && - !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)) { - sta->ptk_idx = idx; - clear_sta_flag(sta, WLAN_STA_BLOCK_BA); - ieee80211_check_fast_xmit(sta); - } + !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)) + _ieee80211_set_tx_key(new, true); } else { rcu_assign_pointer(sta->gtk[idx], new); } diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index d69983370381..38a0383dfbcf 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -1152,7 +1152,8 @@ int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata, } } - if (!(mpath->flags & MESH_PATH_RESOLVING)) + if (!(mpath->flags & MESH_PATH_RESOLVING) && + mesh_path_sel_is_hwmp(sdata)) mesh_queue_preq(mpath, PREQ_Q_F_START); if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0e05ff037672..0ba98ad9bc85 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -4114,7 +4114,7 @@ void __ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata) lockdep_assert_held(&local->sta_mtx); - list_for_each_entry_rcu(sta, &local->sta_list, list) { + list_for_each_entry(sta, &local->sta_list, list) { if (sdata != sta->sdata && (!sta->sdata->bss || sta->sdata->bss != sdata->bss)) continue; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 8d3a2389b055..21b1422b1b1c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -4,7 +4,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation */ #include @@ -1032,6 +1032,11 @@ static void __sta_info_destroy_part2(struct sta_info *sta) might_sleep(); lockdep_assert_held(&local->sta_mtx); + while (sta->sta_state == IEEE80211_STA_AUTHORIZED) { + ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); + WARN_ON_ONCE(ret); + } + /* now keys can no longer be reached */ ieee80211_free_sta_keys(local, sta); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 369c2dddce52..be1d9dfa760d 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -98,6 +98,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_MPSP_OWNER, WLAN_STA_MPSP_RECIPIENT, WLAN_STA_PS_DELIVER, + WLAN_STA_USES_ENCRYPTION, NUM_WLAN_STA_FLAGS, }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cbd273c0b275..41da41cb5c40 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -5,7 +5,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018, 2020 Intel Corporation * * Transmit and frame generation functions. */ @@ -590,10 +590,13 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; - if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) + if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) { tx->key = NULL; - else if (tx->sta && - (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]))) + return TX_CONTINUE; + } + + if (tx->sta && + (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]))) tx->key = key; else if (ieee80211_is_group_privacy_action(tx->skb) && (key = rcu_dereference(tx->sdata->default_multicast_key))) @@ -654,6 +657,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) if (!skip_hw && tx->key && tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) info->control.hw_key = &tx->key->conf; + } else if (!ieee80211_is_mgmt(hdr->frame_control) && tx->sta && + test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) { + return TX_DROP; } return TX_CONTINUE; @@ -3590,8 +3596,26 @@ begin: tx.skb = skb; tx.sdata = vif_to_sdata(info->control.vif); - if (txq->sta) + if (txq->sta) { tx.sta = container_of(txq->sta, struct sta_info, sta); + /* + * Drop unicast frames to unauthorised stations unless they are + * EAPOL frames from the local station. + */ + if (unlikely(ieee80211_is_data(hdr->frame_control) && + !ieee80211_vif_is_mesh(&tx.sdata->vif) && + tx.sdata->vif.type != NL80211_IFTYPE_OCB && + !is_multicast_ether_addr(hdr->addr1) && + !test_sta_flag(tx.sta, WLAN_STA_AUTHORIZED) && + (!(info->control.flags & + IEEE80211_TX_CTRL_PORT_CTRL_PROTO) || + !ether_addr_equal(tx.sdata->vif.addr, + hdr->addr2)))) { + I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); + ieee80211_free_txskb(&local->hw, skb); + goto begin; + } + } /* * The key can be removed while the packet was queued, so need to call @@ -5061,6 +5085,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ethhdr *ehdr; + u32 ctrl_flags = 0; u32 flags; /* Only accept CONTROL_PORT_PROTOCOL configured in CONNECT/ASSOCIATE @@ -5070,6 +5095,9 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, proto != cpu_to_be16(ETH_P_PREAUTH)) return -EINVAL; + if (proto == sdata->control_port_protocol) + ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; + if (unencrypted) flags = IEEE80211_TX_INTFL_DONT_ENCRYPT; else @@ -5095,7 +5123,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, skb_reset_mac_header(skb); local_bh_disable(); - __ieee80211_subif_start_xmit(skb, skb->dev, flags, 0); + __ieee80211_subif_start_xmit(skb, skb->dev, flags, ctrl_flags); local_bh_enable(); return 0; diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 410809c669e1..4912069627b6 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -411,7 +411,7 @@ static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) *pos = cpu + 1; return per_cpu_ptr(net->ct.stat, cpu); } - + (*pos)++; return NULL; } diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c index b9e7dd6e60ce..e92aa6b7eb80 100644 --- a/net/netfilter/nf_flow_table_ip.c +++ b/net/netfilter/nf_flow_table_ip.c @@ -189,6 +189,7 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, if (!pskb_may_pull(skb, thoff + sizeof(*ports))) return -1; + iph = ip_hdr(skb); ports = (struct flow_ports *)(skb_network_header(skb) + thoff); tuple->src_v4.s_addr = iph->saddr; @@ -449,6 +450,7 @@ static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, if (!pskb_may_pull(skb, thoff + sizeof(*ports))) return -1; + ip6h = ipv6_hdr(skb); ports = (struct flow_ports *)(skb_network_header(skb) + thoff); tuple->src_v6 = ip6h->saddr; diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c index b0930d4aba22..b9cbe1e2453e 100644 --- a/net/netfilter/nf_synproxy_core.c +++ b/net/netfilter/nf_synproxy_core.c @@ -267,7 +267,7 @@ static void *synproxy_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) *pos = cpu + 1; return per_cpu_ptr(snet->stats, cpu); } - + (*pos)++; return NULL; } diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 23544842b692..068daff41f6e 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1309,6 +1309,11 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net, lockdep_commit_lock_is_held(net)); if (nft_dump_stats(skb, stats)) goto nla_put_failure; + + if ((chain->flags & NFT_CHAIN_HW_OFFLOAD) && + nla_put_be32(skb, NFTA_CHAIN_FLAGS, + htonl(NFT_CHAIN_HW_OFFLOAD))) + goto nla_put_failure; } if (nla_put_be32(skb, NFTA_CHAIN_USE, htonl(chain->use))) @@ -6970,13 +6975,8 @@ static void nf_tables_module_autoload(struct net *net) list_splice_init(&net->nft.module_list, &module_list); mutex_unlock(&net->nft.commit_mutex); list_for_each_entry_safe(req, next, &module_list, list) { - if (req->done) { - list_del(&req->list); - kfree(req); - } else { - request_module("%s", req->module); - req->done = true; - } + request_module("%s", req->module); + req->done = true; } mutex_lock(&net->nft.commit_mutex); list_splice(&module_list, &net->nft.module_list); @@ -7759,6 +7759,7 @@ static void __net_exit nf_tables_exit_net(struct net *net) __nft_release_tables(net); mutex_unlock(&net->nft.commit_mutex); WARN_ON_ONCE(!list_empty(&net->nft.tables)); + WARN_ON_ONCE(!list_empty(&net->nft.module_list)); } static struct pernet_operations nf_tables_net_ops = { diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index 7525063c25f5..60838d5fb8e0 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -742,6 +742,8 @@ static const struct nla_policy nfnl_cthelper_policy[NFCTH_MAX+1] = { [NFCTH_NAME] = { .type = NLA_NUL_STRING, .len = NF_CT_HELPER_NAME_LEN-1 }, [NFCTH_QUEUE_NUM] = { .type = NLA_U32, }, + [NFCTH_PRIV_DATA_LEN] = { .type = NLA_U32, }, + [NFCTH_STATUS] = { .type = NLA_U32, }, }; static const struct nfnl_callback nfnl_cthelper_cb[NFNL_MSG_CTHELPER_MAX] = { diff --git a/net/netfilter/nft_chain_nat.c b/net/netfilter/nft_chain_nat.c index ff9ac8ae0031..eac4a901233f 100644 --- a/net/netfilter/nft_chain_nat.c +++ b/net/netfilter/nft_chain_nat.c @@ -89,6 +89,7 @@ static const struct nft_chain_type nft_chain_nat_inet = { .name = "nat", .type = NFT_CHAIN_T_NAT, .family = NFPROTO_INET, + .owner = THIS_MODULE, .hook_mask = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_LOCAL_OUT) | diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c index aba11c2333f3..3087e23297db 100644 --- a/net/netfilter/nft_fwd_netdev.c +++ b/net/netfilter/nft_fwd_netdev.c @@ -28,6 +28,9 @@ static void nft_fwd_netdev_eval(const struct nft_expr *expr, struct nft_fwd_netdev *priv = nft_expr_priv(expr); int oif = regs->data[priv->sreg_dev]; + /* This is used by ifb only. */ + skb_set_redirected(pkt->skb, true); + nf_fwd_netdev_egress(pkt, oif); regs->verdict.code = NF_STOLEN; } @@ -190,6 +193,13 @@ nla_put_failure: return -1; } +static int nft_fwd_validate(const struct nft_ctx *ctx, + const struct nft_expr *expr, + const struct nft_data **data) +{ + return nft_chain_validate_hooks(ctx->chain, (1 << NF_NETDEV_INGRESS)); +} + static struct nft_expr_type nft_fwd_netdev_type; static const struct nft_expr_ops nft_fwd_neigh_netdev_ops = { .type = &nft_fwd_netdev_type, @@ -197,6 +207,7 @@ static const struct nft_expr_ops nft_fwd_neigh_netdev_ops = { .eval = nft_fwd_neigh_eval, .init = nft_fwd_neigh_init, .dump = nft_fwd_neigh_dump, + .validate = nft_fwd_validate, }; static const struct nft_expr_ops nft_fwd_netdev_ops = { @@ -205,6 +216,7 @@ static const struct nft_expr_ops nft_fwd_netdev_ops = { .eval = nft_fwd_netdev_eval, .init = nft_fwd_netdev_init, .dump = nft_fwd_netdev_dump, + .validate = nft_fwd_validate, .offload = nft_fwd_netdev_offload, }; diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index 5cb2d8908d2a..0e3bfbc26e79 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -121,6 +121,7 @@ static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, [NFTA_PAYLOAD_CSUM_OFFSET] = { .type = NLA_U32 }, + [NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 }, }; static int nft_payload_init(const struct nft_ctx *ctx, diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c index 037e8fce9b30..1effd4878619 100644 --- a/net/netfilter/nft_tunnel.c +++ b/net/netfilter/nft_tunnel.c @@ -339,6 +339,8 @@ static const struct nla_policy nft_tunnel_key_policy[NFTA_TUNNEL_KEY_MAX + 1] = [NFTA_TUNNEL_KEY_FLAGS] = { .type = NLA_U32, }, [NFTA_TUNNEL_KEY_TOS] = { .type = NLA_U8, }, [NFTA_TUNNEL_KEY_TTL] = { .type = NLA_U8, }, + [NFTA_TUNNEL_KEY_SPORT] = { .type = NLA_U16, }, + [NFTA_TUNNEL_KEY_DPORT] = { .type = NLA_U16, }, [NFTA_TUNNEL_KEY_OPTS] = { .type = NLA_NESTED, }, }; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index ce70c2576bb2..44f971f31992 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -1551,6 +1551,9 @@ static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos, uint8_t nfproto = (unsigned long)PDE_DATA(file_inode(seq->file)); struct nf_mttg_trav *trav = seq->private; + if (ppos != NULL) + ++(*ppos); + switch (trav->class) { case MTTG_TRAV_INIT: trav->class = MTTG_TRAV_NFP_UNSPEC; @@ -1576,9 +1579,6 @@ static void *xt_mttg_seq_next(struct seq_file *seq, void *v, loff_t *ppos, default: return NULL; } - - if (ppos != NULL) - ++*ppos; return trav; } diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 1b68a131083c..8c835ad63729 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -358,21 +358,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg, return 0; } -static bool select_all(const struct xt_hashlimit_htable *ht, - const struct dsthash_ent *he) -{ - return true; -} - -static bool select_gc(const struct xt_hashlimit_htable *ht, - const struct dsthash_ent *he) -{ - return time_after_eq(jiffies, he->expires); -} - -static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, - bool (*select)(const struct xt_hashlimit_htable *ht, - const struct dsthash_ent *he)) +static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, bool select_all) { unsigned int i; @@ -382,7 +368,7 @@ static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, spin_lock_bh(&ht->lock); hlist_for_each_entry_safe(dh, n, &ht->hash[i], node) { - if ((*select)(ht, dh)) + if (time_after_eq(jiffies, dh->expires) || select_all) dsthash_free(ht, dh); } spin_unlock_bh(&ht->lock); @@ -396,7 +382,7 @@ static void htable_gc(struct work_struct *work) ht = container_of(work, struct xt_hashlimit_htable, gc_work.work); - htable_selective_cleanup(ht, select_gc); + htable_selective_cleanup(ht, false); queue_delayed_work(system_power_efficient_wq, &ht->gc_work, msecs_to_jiffies(ht->cfg.gc_interval)); @@ -416,15 +402,6 @@ static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) remove_proc_entry(hinfo->name, parent); } -static void htable_destroy(struct xt_hashlimit_htable *hinfo) -{ - cancel_delayed_work_sync(&hinfo->gc_work); - htable_remove_proc_entry(hinfo); - htable_selective_cleanup(hinfo, select_all); - kfree(hinfo->name); - vfree(hinfo); -} - static struct xt_hashlimit_htable *htable_find_get(struct net *net, const char *name, u_int8_t family) @@ -446,8 +423,13 @@ static void htable_put(struct xt_hashlimit_htable *hinfo) { if (refcount_dec_and_mutex_lock(&hinfo->use, &hashlimit_mutex)) { hlist_del(&hinfo->node); + htable_remove_proc_entry(hinfo); mutex_unlock(&hashlimit_mutex); - htable_destroy(hinfo); + + cancel_delayed_work_sync(&hinfo->gc_work); + htable_selective_cleanup(hinfo, true); + kfree(hinfo->name); + vfree(hinfo); } } diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 781e0b482189..6c2582a19766 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -492,12 +492,12 @@ static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos) const struct recent_entry *e = v; const struct list_head *head = e->list.next; + (*pos)++; while (head == &t->iphash[st->bucket]) { if (++st->bucket >= ip_list_hash_size) return NULL; head = t->iphash[st->bucket].next; } - (*pos)++; return list_entry(head, struct recent_entry, list); } diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index e64b8784d487..c2a5174387ff 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2434,7 +2434,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, in_skb->len)) WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS, (u8 *)extack->bad_attr - - in_skb->data)); + (u8 *)nlh)); } else { if (extack->cookie_len) WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE, diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 6f1b096e601c..43811b5219b5 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c @@ -181,13 +181,20 @@ exit: void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, struct sk_buff *skb) { - u8 gate = hdev->pipes[pipe].gate; u8 status = NFC_HCI_ANY_OK; struct hci_create_pipe_resp *create_info; struct hci_delete_pipe_noti *delete_info; struct hci_all_pipe_cleared_noti *cleared_info; + u8 gate; - pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd); + pr_debug("from pipe %x cmd %x\n", pipe, cmd); + + if (pipe >= NFC_HCI_MAX_PIPES) { + status = NFC_HCI_ANY_E_NOK; + goto exit; + } + + gate = hdev->pipes[pipe].gate; switch (cmd) { case NFC_HCI_ADM_NOTIFY_PIPE_CREATED: @@ -375,8 +382,14 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, struct sk_buff *skb) { int r = 0; - u8 gate = hdev->pipes[pipe].gate; + u8 gate; + if (pipe >= NFC_HCI_MAX_PIPES) { + pr_err("Discarded event %x to invalid pipe %x\n", event, pipe); + goto exit; + } + + gate = hdev->pipes[pipe].gate; if (gate == NFC_HCI_INVALID_GATE) { pr_err("Discarded event %x to unopened pipe %x\n", event, pipe); goto exit; diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index afde0d763039..1b261375722e 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -32,6 +32,7 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING, .len = NFC_DEVICE_NAME_MAXSIZE }, [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 }, + [NFC_ATTR_TARGET_INDEX] = { .type = NLA_U32 }, [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, @@ -43,7 +44,10 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { [NFC_ATTR_LLC_SDP] = { .type = NLA_NESTED }, [NFC_ATTR_FIRMWARE_NAME] = { .type = NLA_STRING, .len = NFC_FIRMWARE_NAME_MAXSIZE }, + [NFC_ATTR_SE_INDEX] = { .type = NLA_U32 }, [NFC_ATTR_SE_APDU] = { .type = NLA_BINARY }, + [NFC_ATTR_VENDOR_ID] = { .type = NLA_U32 }, + [NFC_ATTR_VENDOR_SUBCMD] = { .type = NLA_U32 }, [NFC_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, }; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 118cd66b7516..1d63ab3a878a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2172,6 +2172,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct timespec ts; __u32 ts_status; bool is_drop_n_account = false; + unsigned int slot_id = 0; bool do_vnet = false; /* struct tpacket{2,3}_hdr is aligned to a multiple of TPACKET_ALIGNMENT. @@ -2273,6 +2274,20 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, TP_STATUS_KERNEL, (macoff+snaplen)); if (!h.raw) goto drop_n_account; + + if (po->tp_version <= TPACKET_V2) { + slot_id = po->rx_ring.head; + if (test_bit(slot_id, po->rx_ring.rx_owner_map)) + goto drop_n_account; + __set_bit(slot_id, po->rx_ring.rx_owner_map); + } + + if (do_vnet && + virtio_net_hdr_from_skb(skb, h.raw + macoff - + sizeof(struct virtio_net_hdr), + vio_le(), true, 0)) + goto drop_n_account; + if (po->tp_version <= TPACKET_V2) { packet_increment_rx_head(po, &po->rx_ring); /* @@ -2285,12 +2300,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, status |= TP_STATUS_LOSING; } - if (do_vnet && - virtio_net_hdr_from_skb(skb, h.raw + macoff - - sizeof(struct virtio_net_hdr), - vio_le(), true, 0)) - goto drop_n_account; - po->stats.stats1.tp_packets++; if (copy_skb) { status |= TP_STATUS_COPY; @@ -2378,7 +2387,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, #endif if (po->tp_version <= TPACKET_V2) { + spin_lock(&sk->sk_receive_queue.lock); __packet_set_status(po, h.raw, status); + __clear_bit(slot_id, po->rx_ring.rx_owner_map); + spin_unlock(&sk->sk_receive_queue.lock); sk->sk_data_ready(sk); } else { prb_clear_blk_fill_status(&po->rx_ring); @@ -4275,6 +4287,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, { struct pgv *pg_vec = NULL; struct packet_sock *po = pkt_sk(sk); + unsigned long *rx_owner_map = NULL; int was_running, order = 0; struct packet_ring_buffer *rb; struct sk_buff_head *rb_queue; @@ -4360,6 +4373,12 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, } break; default: + if (!tx_ring) { + rx_owner_map = bitmap_alloc(req->tp_frame_nr, + GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO); + if (!rx_owner_map) + goto out_free_pg_vec; + } break; } } @@ -4389,6 +4408,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, err = 0; spin_lock_bh(&rb_queue->lock); swap(rb->pg_vec, pg_vec); + if (po->tp_version <= TPACKET_V2) + swap(rb->rx_owner_map, rx_owner_map); rb->frame_max = (req->tp_frame_nr - 1); rb->head = 0; rb->frame_size = req->tp_frame_size; @@ -4420,6 +4441,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, } out_free_pg_vec: + bitmap_free(rx_owner_map); if (pg_vec) free_pg_vec(pg_vec, order, req->tp_block_nr); out: diff --git a/net/packet/internal.h b/net/packet/internal.h index 82fb2b10f790..907f4cd2a718 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -70,7 +70,10 @@ struct packet_ring_buffer { unsigned int __percpu *pending_refcnt; - struct tpacket_kbdq_core prb_bdqc; + union { + unsigned long *rx_owner_map; + struct tpacket_kbdq_core prb_bdqc; + }; }; extern struct mutex fanout_mutex; diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 4a6ca9723a12..a293238fe1e7 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -371,44 +371,17 @@ EXPORT_SYMBOL(rxrpc_kernel_end_call); * rxrpc_kernel_check_life - Check to see whether a call is still alive * @sock: The socket the call is on * @call: The call to check - * @_life: Where to store the life value * - * Allow a kernel service to find out whether a call is still alive - ie. we're - * getting ACKs from the server. Passes back in *_life a number representing - * the life state which can be compared to that returned by a previous call and - * return true if the call is still alive. - * - * If the life state stalls, rxrpc_kernel_probe_life() should be called and - * then 2RTT waited. + * Allow a kernel service to find out whether a call is still alive - + * ie. whether it has completed. */ bool rxrpc_kernel_check_life(const struct socket *sock, - const struct rxrpc_call *call, - u32 *_life) + const struct rxrpc_call *call) { - *_life = call->acks_latest; return call->state != RXRPC_CALL_COMPLETE; } EXPORT_SYMBOL(rxrpc_kernel_check_life); -/** - * rxrpc_kernel_probe_life - Poke the peer to see if it's still alive - * @sock: The socket the call is on - * @call: The call to check - * - * In conjunction with rxrpc_kernel_check_life(), allow a kernel service to - * find out whether a call is still alive by pinging it. This should cause the - * life state to be bumped in about 2*RTT. - * - * The must be called in TASK_RUNNING state on pain of might_sleep() objecting. - */ -void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call) -{ - rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, - rxrpc_propose_ack_ping_for_check_life); - rxrpc_send_ack_packet(call, true, NULL); -} -EXPORT_SYMBOL(rxrpc_kernel_probe_life); - /** * rxrpc_kernel_get_epoch - Retrieve the epoch value from a call. * @sock: The socket the call is on diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 7d730c438404..394d18857979 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -675,7 +675,6 @@ struct rxrpc_call { /* transmission-phase ACK management */ ktime_t acks_latest_ts; /* Timestamp of latest ACK received */ - rxrpc_serial_t acks_latest; /* serial number of latest ACK received */ rxrpc_seq_t acks_lowest_nak; /* Lowest NACK in the buffer (or ==tx_hard_ack) */ rxrpc_seq_t acks_lost_top; /* tx_top at the time lost-ack ping sent */ rxrpc_serial_t acks_lost_ping; /* Serial number of probe ACK */ diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index ef10fbf71b15..69e09d69c896 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -882,7 +882,6 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) before(prev_pkt, call->ackr_prev_seq)) goto out; call->acks_latest_ts = skb->tstamp; - call->acks_latest = sp->hdr.serial; call->ackr_first_seq = first_soft_ack; call->ackr_prev_seq = prev_pkt; diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c index f3232a00970f..0586546c20d7 100644 --- a/net/sched/act_ct.c +++ b/net/sched/act_ct.c @@ -739,7 +739,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla, if (goto_ch) tcf_chain_put_by_act(goto_ch); if (params) - kfree_rcu(params, rcu); + call_rcu(¶ms->rcu, tcf_ct_params_free); if (res == ACT_P_CREATED) tcf_idr_insert(tn, *a); diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index f0df0d90b8bd..27f624971121 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -284,10 +284,8 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a, /* mirror is always swallowed */ if (is_redirect) { - skb2->tc_redirected = 1; - skb2->tc_from_ingress = skb2->tc_at_ingress; - if (skb2->tc_from_ingress) - skb2->tstamp = 0; + skb_set_redirected(skb2, skb2->tc_at_ingress); + /* let's the caller reinsert the packet, if possible */ if (use_reinsert) { res->ingress = want_ingress; diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 6f8786b06bde..5efa3e7ace15 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -534,8 +534,8 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, fp = &b->ht[h]; for (pfp = rtnl_dereference(*fp); pfp; fp = &pfp->next, pfp = rtnl_dereference(*fp)) { - if (pfp == f) { - *fp = f->next; + if (pfp == fold) { + rcu_assign_pointer(*fp, fold->next); break; } } diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 09b7dc5fe7e0..9904299424a1 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -261,8 +261,10 @@ static void tcindex_partial_destroy_work(struct work_struct *work) struct tcindex_data, rwork); + rtnl_lock(); kfree(p->perfect); kfree(p); + rtnl_unlock(); } static void tcindex_free_perfect_hash(struct tcindex_data *cp) @@ -357,6 +359,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, if (tcindex_alloc_perfect_hash(net, cp) < 0) goto errout; + cp->alloc_hash = cp->hash; for (i = 0; i < min(cp->hash, p->hash); i++) cp->perfect[i].res = p->perfect[i].res; balloc = 1; diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c index b2905b03a432..2eaac2ff380f 100644 --- a/net/sched/sch_cbs.c +++ b/net/sched/sch_cbs.c @@ -181,6 +181,11 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch) s64 credits; int len; + /* The previous packet is still being sent */ + if (now < q->last) { + qdisc_watchdog_schedule_ns(&q->watchdog, q->last); + return NULL; + } if (q->credits < 0) { credits = timediff_to_credits(now - q->last, q->idleslope); @@ -212,7 +217,12 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch) credits += q->credits; q->credits = max_t(s64, credits, q->locredit); - q->last = now; + /* Estimate of the transmission of the last byte of the packet in ns */ + if (unlikely(atomic64_read(&q->port_rate) == 0)) + q->last = now; + else + q->last = now + div64_s64(len * NSEC_PER_SEC, + atomic64_read(&q->port_rate)); return skb; } diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 712ad248d6a7..f757ea90aba6 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c @@ -745,6 +745,7 @@ static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = { [TCA_FQ_FLOW_MAX_RATE] = { .type = NLA_U32 }, [TCA_FQ_BUCKETS_LOG] = { .type = NLA_U32 }, [TCA_FQ_FLOW_REFILL_DELAY] = { .type = NLA_U32 }, + [TCA_FQ_ORPHAN_MASK] = { .type = NLA_U32 }, [TCA_FQ_LOW_RATE_THRESHOLD] = { .type = NLA_U32 }, [TCA_FQ_CE_THRESHOLD] = { .type = NLA_U32 }, }; diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index 660fc45ee40f..b1eb12d33b9a 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -564,8 +564,10 @@ static struct sk_buff *taprio_dequeue_soft(struct Qdisc *sch) prio = skb->priority; tc = netdev_get_prio_tc_map(dev, prio); - if (!(gate_mask & BIT(tc))) + if (!(gate_mask & BIT(tc))) { + skb = NULL; continue; + } len = qdisc_pkt_len(skb); guard = ktime_add_ns(taprio_get_time(q), @@ -575,13 +577,17 @@ static struct sk_buff *taprio_dequeue_soft(struct Qdisc *sch) * guard band ... */ if (gate_mask != TAPRIO_ALL_GATES_OPEN && - ktime_after(guard, entry->close_time)) + ktime_after(guard, entry->close_time)) { + skb = NULL; continue; + } /* ... and no budget. */ if (gate_mask != TAPRIO_ALL_GATES_OPEN && - atomic_sub_return(len, &entry->budget) < 0) + atomic_sub_return(len, &entry->budget) < 0) { + skb = NULL; continue; + } skb = child->ops->dequeue(child); if (unlikely(!skb)) @@ -768,6 +774,7 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = { [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME] = { .type = NLA_S64 }, [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 }, [TCA_TAPRIO_ATTR_FLAGS] = { .type = NLA_U32 }, + [TCA_TAPRIO_ATTR_TXTIME_DELAY] = { .type = NLA_U32 }, }; static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry, diff --git a/net/sctp/diag.c b/net/sctp/diag.c index 0851166b9175..ba9f64fdfd23 100644 --- a/net/sctp/diag.c +++ b/net/sctp/diag.c @@ -237,15 +237,11 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc) addrcnt++; return nla_total_size(sizeof(struct sctp_info)) - + nla_total_size(1) /* INET_DIAG_SHUTDOWN */ - + nla_total_size(1) /* INET_DIAG_TOS */ - + nla_total_size(1) /* INET_DIAG_TCLASS */ - + nla_total_size(4) /* INET_DIAG_MARK */ - + nla_total_size(4) /* INET_DIAG_CLASS_ID */ + nla_total_size(addrlen * asoc->peer.transport_count) + nla_total_size(addrlen * addrcnt) - + nla_total_size(sizeof(struct inet_diag_meminfo)) + nla_total_size(sizeof(struct inet_diag_msg)) + + inet_diag_msg_attrs_size() + + nla_total_size(sizeof(struct inet_diag_meminfo)) + 64; } diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c index d14ca4af6f94..d74a71dff5b8 100644 --- a/net/smc/smc_ib.c +++ b/net/smc/smc_ib.c @@ -560,12 +560,15 @@ static void smc_ib_remove_dev(struct ib_device *ibdev, void *client_data) struct smc_ib_device *smcibdev; smcibdev = ib_get_client_data(ibdev, &smc_ib_client); + if (!smcibdev || smcibdev->ibdev != ibdev) + return; ib_set_client_data(ibdev, &smc_ib_client, NULL); spin_lock(&smc_ib_devices.lock); list_del_init(&smcibdev->list); /* remove from smc_ib_devices */ spin_unlock(&smc_ib_devices.lock); smc_ib_cleanup_per_ibdev(smcibdev); ib_unregister_event_handler(&smcibdev->event_handler); + cancel_work_sync(&smcibdev->port_event_work); kfree(smcibdev); } diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index d6165ad384c0..e9bbf4a00881 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c @@ -111,6 +111,7 @@ const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 }, [TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 }, [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 } }; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4ac6e53b0670..1ec9fa5b33fb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -469,6 +469,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, [NL80211_ATTR_STA_PLINK_STATE] = NLA_POLICY_MAX(NLA_U8, NUM_NL80211_PLINK_STATES - 1), + [NL80211_ATTR_MEASUREMENT_DURATION] = { .type = NLA_U16 }, + [NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY] = { .type = NLA_FLAG }, [NL80211_ATTR_MESH_PEER_AID] = NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID), [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, @@ -530,6 +532,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_MDID] = { .type = NLA_U16 }, [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_CRIT_PROT_ID] = { .type = NLA_U16 }, + [NL80211_ATTR_MAX_CRIT_PROT_DURATION] = { .type = NLA_U16 }, [NL80211_ATTR_PEER_AID] = NLA_POLICY_RANGE(NLA_U16, 1, IEEE80211_MAX_AID), [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 }, @@ -560,6 +564,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { NLA_POLICY_MAX(NLA_U8, IEEE80211_NUM_UPS - 1), [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 }, [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 }, + [NL80211_ATTR_OPER_CLASS] = { .type = NLA_U8 }, [NL80211_ATTR_MAC_MASK] = { .type = NLA_EXACT_LEN_WARN, .len = ETH_ALEN @@ -16413,7 +16418,7 @@ void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac, goto nla_put_failure; if ((sta_opmode->changed & STA_OPMODE_MAX_BW_CHANGED) && - nla_put_u8(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw)) + nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, sta_opmode->bw)) goto nla_put_failure; if ((sta_opmode->changed & STA_OPMODE_N_SS_CHANGED) && diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 9243078d88ad..891b9bf95b5e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2313,7 +2313,7 @@ static void handle_channel_custom(struct wiphy *wiphy, break; } - if (IS_ERR(reg_rule)) { + if (IS_ERR_OR_NULL(reg_rule)) { pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n", chan->center_freq); if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 189ef15acbbc..64486ad81341 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -390,6 +390,7 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void return xfrm_dev_feat_change(dev); case NETDEV_DOWN: + case NETDEV_UNREGISTER: return xfrm_dev_down(dev); } return NOTIFY_DONE; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index f2d1e573ea55..264cf05a4eaa 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -431,7 +431,9 @@ EXPORT_SYMBOL(xfrm_policy_destroy); static void xfrm_policy_kill(struct xfrm_policy *policy) { + write_lock_bh(&policy->lock); policy->walk.dead = 1; + write_unlock_bh(&policy->lock); atomic_inc(&policy->genid); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index ed6e6790b3e7..677d0b94b3b6 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -110,7 +110,8 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs) return 0; uctx = nla_data(rt); - if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len)) + if (uctx->len > nla_len(rt) || + uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len)) return -EINVAL; return 0; @@ -2273,6 +2274,9 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, xfrm_mark_get(attrs, &mark); err = verify_newpolicy_info(&ua->policy); + if (err) + goto free_state; + err = verify_sec_ctx_len(attrs); if (err) goto free_state; diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c index c58504774118..418c46fe5ffc 100644 --- a/samples/hw_breakpoint/data_breakpoint.c +++ b/samples/hw_breakpoint/data_breakpoint.c @@ -23,7 +23,7 @@ struct perf_event * __percpu *sample_hbp; -static char ksym_name[KSYM_NAME_LEN] = "pid_max"; +static char ksym_name[KSYM_NAME_LEN] = "jiffies"; module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO); MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any" " write operations on the kernel symbol"); @@ -41,11 +41,15 @@ static int __init hw_break_module_init(void) { int ret; struct perf_event_attr attr; + void *addr = __symbol_get(ksym_name); + + if (!addr) + return -ENXIO; hw_breakpoint_init(&attr); - attr.bp_addr = kallsyms_lookup_name(ksym_name); + attr.bp_addr = (unsigned long)addr; attr.bp_len = HW_BREAKPOINT_LEN_4; - attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; + attr.bp_type = HW_BREAKPOINT_W; sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler, NULL); if (IS_ERR((void __force *)sample_hbp)) { @@ -66,6 +70,7 @@ fail: static void __exit hw_break_module_exit(void) { unregister_wide_hw_breakpoint(sample_hbp); + symbol_put(ksym_name); printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name); } diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index ecddf83ac142..ca08f2fe7c34 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -48,6 +48,7 @@ KBUILD_CFLAGS += -Wno-initializer-overrides KBUILD_CFLAGS += -Wno-format KBUILD_CFLAGS += -Wno-sign-compare KBUILD_CFLAGS += -Wno-format-zero-length +KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast) endif endif diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index 5c6c3fd557d7..b3b7270300de 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l @@ -23,7 +23,6 @@ LINECOMMENT "//".*\n #include "srcpos.h" #include "dtc-parser.tab.h" -YYLTYPE yylloc; extern bool treesource_error; /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ diff --git a/scripts/export_report.pl b/scripts/export_report.pl index 548330e8c4e7..feb3d5542a62 100755 --- a/scripts/export_report.pl +++ b/scripts/export_report.pl @@ -94,7 +94,7 @@ if (defined $opt{'o'}) { # while ( <$module_symvers> ) { chomp; - my (undef, $symbol, $namespace, $module, $gpl) = split('\t'); + my (undef, $symbol, $module, $gpl, $namespace) = split('\t'); $SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl]; } close($module_symvers); diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index d780dde5136d..9752b9ca6b6c 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -27,7 +27,7 @@ if [ -n "$CONFIG_UNUSED_KSYMS_WHITELIST" ]; then eval ksym_wl="$UNUSED_KSYMS_WHITELIST_FILE" [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" - if [ ! -f "$ksym_wl" ]; then + if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then echo "ERROR: '$ksym_wl' whitelist file not found" >&2 exit 1 fi diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 6ef098430b86..f83adf736e3a 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2441,7 +2441,7 @@ static void write_if_changed(struct buffer *b, const char *fname) } /* parse Module.symvers file. line format: - * 0x12345678symbolmodule[[export]something] + * 0x12345678symbolmoduleexportnamespace **/ static void read_dump(const char *fname, unsigned int kernel) { @@ -2454,7 +2454,7 @@ static void read_dump(const char *fname, unsigned int kernel) return; while ((line = get_next_line(&pos, file, size))) { - char *symname, *namespace, *modname, *d, *export, *end; + char *symname, *namespace, *modname, *d, *export; unsigned int crc; struct module *mod; struct symbol *s; @@ -2462,16 +2462,16 @@ static void read_dump(const char *fname, unsigned int kernel) if (!(symname = strchr(line, '\t'))) goto fail; *symname++ = '\0'; - if (!(namespace = strchr(symname, '\t'))) - goto fail; - *namespace++ = '\0'; - if (!(modname = strchr(namespace, '\t'))) + if (!(modname = strchr(symname, '\t'))) goto fail; *modname++ = '\0'; - if ((export = strchr(modname, '\t')) != NULL) - *export++ = '\0'; - if (export && ((end = strchr(export, '\t')) != NULL)) - *end = '\0'; + if (!(export = strchr(modname, '\t'))) + goto fail; + *export++ = '\0'; + if (!(namespace = strchr(export, '\t'))) + goto fail; + *namespace++ = '\0'; + crc = strtoul(line, &d, 16); if (*symname == '\0' || *modname == '\0' || *d != '\0') goto fail; @@ -2523,9 +2523,9 @@ static void write_dump(const char *fname) namespace = symbol->namespace; buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n", symbol->crc, symbol->name, - namespace ? namespace : "", symbol->module->name, - export_str(symbol->export)); + export_str(symbol->export), + namespace ? namespace : ""); } symbol = symbol->next; } diff --git a/scripts/module-lto.lds b/scripts/module-lto.lds index f5ee544a877d..5ba0e9461e13 100644 --- a/scripts/module-lto.lds +++ b/scripts/module-lto.lds @@ -12,11 +12,11 @@ SECTIONS { *(.eh_frame) } - .bss : { *(.bss .bss[.0-9a-zA-Z_]*) } - .data : { *(.data .data[.0-9a-zA-Z_]*) } - .rela.data : { *(.rela.data .rela.data[.0-9a-zA-Z_]*) } - .rela.rodata : { *(.rela.rodata .rela.rodata[.0-9a-zA-Z_]*) } - .rela.text : { *(.rela.text .rela.text[.0-9a-zA-Z_]*) } - .rodata : { *(.rodata .rodata[.0-9a-zA-Z_]*) } - .text : { *(.text .text[.0-9a-zA-Z_]*) } + .bss : { *(.bss .bss.[0-9a-zA-Z_]*) } + .data : { *(.data .data.[0-9a-zA-Z_]*) } + .rela.data : { *(.rela.data .rela.data.[0-9a-zA-Z_]*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.[0-9a-zA-Z_]*) } + .rela.text : { *(.rela.text .rela.text.[0-9a-zA-Z_]*) } + .rodata : { *(.rodata .rodata.[0-9a-zA-Z_]*) } + .text : { *(.text .text.[0-9a-zA-Z_]*) } } diff --git a/scripts/parse-maintainers.pl b/scripts/parse-maintainers.pl old mode 100644 new mode 100755 diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c index 81b19c52832b..020fc7a11ef0 100644 --- a/security/integrity/platform_certs/load_uefi.c +++ b/security/integrity/platform_certs/load_uefi.c @@ -39,16 +39,18 @@ static __init bool uefi_check_ignore_db(void) * Get a certificate list blob from the named EFI variable. */ static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, - unsigned long *size) + unsigned long *size, efi_status_t *status) { - efi_status_t status; unsigned long lsize = 4; unsigned long tmpdb[4]; void *db; - status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); - if (status != EFI_BUFFER_TOO_SMALL) { - pr_err("Couldn't get size: 0x%lx\n", status); + *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); + if (*status == EFI_NOT_FOUND) + return NULL; + + if (*status != EFI_BUFFER_TOO_SMALL) { + pr_err("Couldn't get size: 0x%lx\n", *status); return NULL; } @@ -56,10 +58,10 @@ static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, if (!db) return NULL; - status = efi.get_variable(name, guid, NULL, &lsize, db); - if (status != EFI_SUCCESS) { + *status = efi.get_variable(name, guid, NULL, &lsize, db); + if (*status != EFI_SUCCESS) { kfree(db); - pr_err("Error reading db var: 0x%lx\n", status); + pr_err("Error reading db var: 0x%lx\n", *status); return NULL; } @@ -144,6 +146,7 @@ static int __init load_uefi_certs(void) efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; void *db = NULL, *dbx = NULL, *mok = NULL; unsigned long dbsize = 0, dbxsize = 0, moksize = 0; + efi_status_t status; int rc = 0; if (!efi.get_variable) @@ -153,9 +156,12 @@ static int __init load_uefi_certs(void) * an error if we can't get them. */ if (!uefi_check_ignore_db()) { - db = get_cert_list(L"db", &secure_var, &dbsize); + db = get_cert_list(L"db", &secure_var, &dbsize, &status); if (!db) { - pr_err("MODSIGN: Couldn't get UEFI db list\n"); + if (status == EFI_NOT_FOUND) + pr_debug("MODSIGN: db variable wasn't found\n"); + else + pr_err("MODSIGN: Couldn't get UEFI db list\n"); } else { rc = parse_efi_signature_list("UEFI:db", db, dbsize, get_handler_for_db); @@ -166,9 +172,12 @@ static int __init load_uefi_certs(void) } } - mok = get_cert_list(L"MokListRT", &mok_var, &moksize); + mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status); if (!mok) { - pr_info("Couldn't get UEFI MokListRT\n"); + if (status == EFI_NOT_FOUND) + pr_debug("MokListRT variable wasn't found\n"); + else + pr_info("Couldn't get UEFI MokListRT\n"); } else { rc = parse_efi_signature_list("UEFI:MokListRT", mok, moksize, get_handler_for_db); @@ -177,9 +186,12 @@ static int __init load_uefi_certs(void) kfree(mok); } - dbx = get_cert_list(L"dbx", &secure_var, &dbxsize); + dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status); if (!dbx) { - pr_info("Couldn't get UEFI dbx list\n"); + if (status == EFI_NOT_FOUND) + pr_debug("dbx variable wasn't found\n"); + else + pr_info("Couldn't get UEFI dbx list\n"); } else { rc = parse_efi_signature_list("UEFI:dbx", dbx, dbxsize, diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 31cb2acf8afc..732bbede7ebf 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -111,7 +111,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) while (plugin->next) { if (plugin->dst_frames) frames = plugin->dst_frames(plugin, frames); - if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0)) + if ((snd_pcm_sframes_t)frames <= 0) return -ENXIO; plugin = plugin->next; err = snd_pcm_plugin_alloc(plugin, frames); @@ -123,7 +123,7 @@ int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames) while (plugin->prev) { if (plugin->src_frames) frames = plugin->src_frames(plugin, frames); - if (snd_BUG_ON((snd_pcm_sframes_t)frames <= 0)) + if ((snd_pcm_sframes_t)frames <= 0) return -ENXIO; plugin = plugin->prev; err = snd_pcm_plugin_alloc(plugin, frames); @@ -209,6 +209,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p if (stream == SNDRV_PCM_STREAM_PLAYBACK) { plugin = snd_pcm_plug_last(plug); while (plugin && drv_frames > 0) { + if (drv_frames > plugin->buf_frames) + drv_frames = plugin->buf_frames; plugin_prev = plugin->prev; if (plugin->src_frames) drv_frames = plugin->src_frames(plugin, drv_frames); @@ -220,6 +222,8 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_p plugin_next = plugin->next; if (plugin->dst_frames) drv_frames = plugin->dst_frames(plugin, drv_frames); + if (drv_frames > plugin->buf_frames) + drv_frames = plugin->buf_frames; plugin = plugin_next; } } else @@ -248,11 +252,15 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc if (frames < 0) return frames; } + if (frames > plugin->buf_frames) + frames = plugin->buf_frames; plugin = plugin_next; } } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { plugin = snd_pcm_plug_last(plug); while (plugin) { + if (frames > plugin->buf_frames) + frames = plugin->buf_frames; plugin_prev = plugin->prev; if (plugin->src_frames) { frames = plugin->src_frames(plugin, frames); diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index a88c235b2ea3..2ddfe2226651 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -602,6 +602,7 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq len = snd_seq_oss_timer_start(dp->timer); if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { snd_seq_oss_readq_sysex(dp->readq, mdev->seq_device, ev); + snd_midi_event_reset_decode(mdev->coder); } else { len = snd_midi_event_decode(mdev->coder, msg, sizeof(msg), ev); if (len > 0) diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 626d87c1539b..77d7037d1476 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -81,6 +81,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) continue; snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream); + snd_midi_event_reset_decode(vmidi->parser); } else { len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev); if (len > 0) diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index cfab60d88c92..09ff209df4a3 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -254,6 +254,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all); int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link) { + unsigned long codec_mask; int ret = 0; mutex_lock(&bus->lock); @@ -280,9 +281,11 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, * HDA spec section 4.3 - Codec Discovery */ udelay(521); - bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS); - dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask); - snd_hdac_chip_writew(bus, STATESTS, bus->codec_mask); + codec_mask = snd_hdac_chip_readw(bus, STATESTS); + dev_dbg(bus->dev, "codec_mask = 0x%lx\n", codec_mask); + snd_hdac_chip_writew(bus, STATESTS, codec_mask); + if (!bus->codec_mask) + bus->codec_mask = codec_mask; } mutex_unlock(&bus->lock); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4f78b40831d8..128db2e6bc64 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -949,7 +949,7 @@ struct alc_codec_rename_pci_table { const char *name; }; -static struct alc_codec_rename_table rename_tbl[] = { +static const struct alc_codec_rename_table rename_tbl[] = { { 0x10ec0221, 0xf00f, 0x1003, "ALC231" }, { 0x10ec0269, 0xfff0, 0x3010, "ALC277" }, { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" }, @@ -970,7 +970,7 @@ static struct alc_codec_rename_table rename_tbl[] = { { } /* terminator */ }; -static struct alc_codec_rename_pci_table rename_pci_tbl[] = { +static const struct alc_codec_rename_pci_table rename_pci_tbl[] = { { 0x10ec0280, 0x1028, 0, "ALC3220" }, { 0x10ec0282, 0x1028, 0, "ALC3221" }, { 0x10ec0283, 0x1028, 0, "ALC3223" }, @@ -2447,6 +2447,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), + SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950), @@ -2999,7 +3000,7 @@ static void alc269_shutup(struct hda_codec *codec) alc_shutup_pins(codec); } -static struct coef_fw alc282_coefs[] = { +static const struct coef_fw alc282_coefs[] = { WRITE_COEF(0x03, 0x0002), /* Power Down Control */ UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */ WRITE_COEF(0x07, 0x0200), /* DMIC control */ @@ -3111,7 +3112,7 @@ static void alc282_shutup(struct hda_codec *codec) alc_write_coef_idx(codec, 0x78, coef78); } -static struct coef_fw alc283_coefs[] = { +static const struct coef_fw alc283_coefs[] = { WRITE_COEF(0x03, 0x0002), /* Power Down Control */ UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */ WRITE_COEF(0x07, 0x0200), /* DMIC control */ @@ -4187,7 +4188,7 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, } } -static struct coef_fw alc225_pre_hsmode[] = { +static const struct coef_fw alc225_pre_hsmode[] = { UPDATE_COEF(0x4a, 1<<8, 0), UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), UPDATE_COEF(0x63, 3<<14, 3<<14), @@ -4200,7 +4201,7 @@ static struct coef_fw alc225_pre_hsmode[] = { static void alc_headset_mode_unplugged(struct hda_codec *codec) { - static struct coef_fw coef0255[] = { + static const struct coef_fw coef0255[] = { WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */ WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */ UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/ @@ -4208,7 +4209,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */ {} }; - static struct coef_fw coef0256[] = { + static const struct coef_fw coef0256[] = { WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */ WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */ WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */ @@ -4216,7 +4217,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/ {} }; - static struct coef_fw coef0233[] = { + static const struct coef_fw coef0233[] = { WRITE_COEF(0x1b, 0x0c0b), WRITE_COEF(0x45, 0xc429), UPDATE_COEF(0x35, 0x4000, 0), @@ -4226,7 +4227,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) WRITE_COEF(0x32, 0x42a3), {} }; - static struct coef_fw coef0288[] = { + static const struct coef_fw coef0288[] = { UPDATE_COEF(0x4f, 0xfcc0, 0xc400), UPDATE_COEF(0x50, 0x2000, 0x2000), UPDATE_COEF(0x56, 0x0006, 0x0006), @@ -4234,18 +4235,18 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) UPDATE_COEF(0x67, 0x2000, 0), {} }; - static struct coef_fw coef0298[] = { + static const struct coef_fw coef0298[] = { UPDATE_COEF(0x19, 0x1300, 0x0300), {} }; - static struct coef_fw coef0292[] = { + static const struct coef_fw coef0292[] = { WRITE_COEF(0x76, 0x000e), WRITE_COEF(0x6c, 0x2400), WRITE_COEF(0x18, 0x7308), WRITE_COEF(0x6b, 0xc429), {} }; - static struct coef_fw coef0293[] = { + static const struct coef_fw coef0293[] = { UPDATE_COEF(0x10, 7<<8, 6<<8), /* SET Line1 JD to 0 */ UPDATE_COEFEX(0x57, 0x05, 1<<15|1<<13, 0x0), /* SET charge pump by verb */ UPDATE_COEFEX(0x57, 0x03, 1<<10, 1<<10), /* SET EN_OSW to 1 */ @@ -4254,16 +4255,16 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */ {} }; - static struct coef_fw coef0668[] = { + static const struct coef_fw coef0668[] = { WRITE_COEF(0x15, 0x0d40), WRITE_COEF(0xb7, 0x802b), {} }; - static struct coef_fw coef0225[] = { + static const struct coef_fw coef0225[] = { UPDATE_COEF(0x63, 3<<14, 0), {} }; - static struct coef_fw coef0274[] = { + static const struct coef_fw coef0274[] = { UPDATE_COEF(0x4a, 0x0100, 0), UPDATE_COEFEX(0x57, 0x05, 0x4000, 0), UPDATE_COEF(0x6b, 0xf000, 0x5000), @@ -4328,25 +4329,25 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, hda_nid_t mic_pin) { - static struct coef_fw coef0255[] = { + static const struct coef_fw coef0255[] = { WRITE_COEFEX(0x57, 0x03, 0x8aa6), WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */ {} }; - static struct coef_fw coef0256[] = { + static const struct coef_fw coef0256[] = { UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14), /* Direct Drive HP Amp control(Set to verb control)*/ WRITE_COEFEX(0x57, 0x03, 0x09a3), WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */ {} }; - static struct coef_fw coef0233[] = { + static const struct coef_fw coef0233[] = { UPDATE_COEF(0x35, 0, 1<<14), WRITE_COEF(0x06, 0x2100), WRITE_COEF(0x1a, 0x0021), WRITE_COEF(0x26, 0x008c), {} }; - static struct coef_fw coef0288[] = { + static const struct coef_fw coef0288[] = { UPDATE_COEF(0x4f, 0x00c0, 0), UPDATE_COEF(0x50, 0x2000, 0), UPDATE_COEF(0x56, 0x0006, 0), @@ -4355,30 +4356,30 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, UPDATE_COEF(0x67, 0x2000, 0x2000), {} }; - static struct coef_fw coef0292[] = { + static const struct coef_fw coef0292[] = { WRITE_COEF(0x19, 0xa208), WRITE_COEF(0x2e, 0xacf0), {} }; - static struct coef_fw coef0293[] = { + static const struct coef_fw coef0293[] = { UPDATE_COEFEX(0x57, 0x05, 0, 1<<15|1<<13), /* SET charge pump by verb */ UPDATE_COEFEX(0x57, 0x03, 1<<10, 0), /* SET EN_OSW to 0 */ UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */ {} }; - static struct coef_fw coef0688[] = { + static const struct coef_fw coef0688[] = { WRITE_COEF(0xb7, 0x802b), WRITE_COEF(0xb5, 0x1040), UPDATE_COEF(0xc3, 0, 1<<12), {} }; - static struct coef_fw coef0225[] = { + static const struct coef_fw coef0225[] = { UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14), UPDATE_COEF(0x4a, 3<<4, 2<<4), UPDATE_COEF(0x63, 3<<14, 0), {} }; - static struct coef_fw coef0274[] = { + static const struct coef_fw coef0274[] = { UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000), UPDATE_COEF(0x4a, 0x0010, 0), UPDATE_COEF(0x6b, 0xf000, 0), @@ -4464,7 +4465,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, static void alc_headset_mode_default(struct hda_codec *codec) { - static struct coef_fw coef0225[] = { + static const struct coef_fw coef0225[] = { UPDATE_COEF(0x45, 0x3f<<10, 0x30<<10), UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10), UPDATE_COEF(0x49, 3<<8, 0<<8), @@ -4473,14 +4474,14 @@ static void alc_headset_mode_default(struct hda_codec *codec) UPDATE_COEF(0x67, 0xf000, 0x3000), {} }; - static struct coef_fw coef0255[] = { + static const struct coef_fw coef0255[] = { WRITE_COEF(0x45, 0xc089), WRITE_COEF(0x45, 0xc489), WRITE_COEFEX(0x57, 0x03, 0x8ea6), WRITE_COEF(0x49, 0x0049), {} }; - static struct coef_fw coef0256[] = { + static const struct coef_fw coef0256[] = { WRITE_COEF(0x45, 0xc489), WRITE_COEFEX(0x57, 0x03, 0x0da3), WRITE_COEF(0x49, 0x0049), @@ -4488,12 +4489,12 @@ static void alc_headset_mode_default(struct hda_codec *codec) WRITE_COEF(0x06, 0x6100), {} }; - static struct coef_fw coef0233[] = { + static const struct coef_fw coef0233[] = { WRITE_COEF(0x06, 0x2100), WRITE_COEF(0x32, 0x4ea3), {} }; - static struct coef_fw coef0288[] = { + static const struct coef_fw coef0288[] = { UPDATE_COEF(0x4f, 0xfcc0, 0xc400), /* Set to TRS type */ UPDATE_COEF(0x50, 0x2000, 0x2000), UPDATE_COEF(0x56, 0x0006, 0x0006), @@ -4501,26 +4502,26 @@ static void alc_headset_mode_default(struct hda_codec *codec) UPDATE_COEF(0x67, 0x2000, 0), {} }; - static struct coef_fw coef0292[] = { + static const struct coef_fw coef0292[] = { WRITE_COEF(0x76, 0x000e), WRITE_COEF(0x6c, 0x2400), WRITE_COEF(0x6b, 0xc429), WRITE_COEF(0x18, 0x7308), {} }; - static struct coef_fw coef0293[] = { + static const struct coef_fw coef0293[] = { UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */ WRITE_COEF(0x45, 0xC429), /* Set to TRS type */ UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */ {} }; - static struct coef_fw coef0688[] = { + static const struct coef_fw coef0688[] = { WRITE_COEF(0x11, 0x0041), WRITE_COEF(0x15, 0x0d40), WRITE_COEF(0xb7, 0x802b), {} }; - static struct coef_fw coef0274[] = { + static const struct coef_fw coef0274[] = { WRITE_COEF(0x45, 0x4289), UPDATE_COEF(0x4a, 0x0010, 0x0010), UPDATE_COEF(0x6b, 0x0f00, 0), @@ -4583,53 +4584,53 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) { int val; - static struct coef_fw coef0255[] = { + static const struct coef_fw coef0255[] = { WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */ WRITE_COEF(0x1b, 0x0c2b), WRITE_COEFEX(0x57, 0x03, 0x8ea6), {} }; - static struct coef_fw coef0256[] = { + static const struct coef_fw coef0256[] = { WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */ WRITE_COEF(0x1b, 0x0e6b), {} }; - static struct coef_fw coef0233[] = { + static const struct coef_fw coef0233[] = { WRITE_COEF(0x45, 0xd429), WRITE_COEF(0x1b, 0x0c2b), WRITE_COEF(0x32, 0x4ea3), {} }; - static struct coef_fw coef0288[] = { + static const struct coef_fw coef0288[] = { UPDATE_COEF(0x50, 0x2000, 0x2000), UPDATE_COEF(0x56, 0x0006, 0x0006), UPDATE_COEF(0x66, 0x0008, 0), UPDATE_COEF(0x67, 0x2000, 0), {} }; - static struct coef_fw coef0292[] = { + static const struct coef_fw coef0292[] = { WRITE_COEF(0x6b, 0xd429), WRITE_COEF(0x76, 0x0008), WRITE_COEF(0x18, 0x7388), {} }; - static struct coef_fw coef0293[] = { + static const struct coef_fw coef0293[] = { WRITE_COEF(0x45, 0xd429), /* Set to ctia type */ UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */ {} }; - static struct coef_fw coef0688[] = { + static const struct coef_fw coef0688[] = { WRITE_COEF(0x11, 0x0001), WRITE_COEF(0x15, 0x0d60), WRITE_COEF(0xc3, 0x0000), {} }; - static struct coef_fw coef0225_1[] = { + static const struct coef_fw coef0225_1[] = { UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10), UPDATE_COEF(0x63, 3<<14, 2<<14), {} }; - static struct coef_fw coef0225_2[] = { + static const struct coef_fw coef0225_2[] = { UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10), UPDATE_COEF(0x63, 3<<14, 1<<14), {} @@ -4701,48 +4702,48 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) /* Nokia type */ static void alc_headset_mode_omtp(struct hda_codec *codec) { - static struct coef_fw coef0255[] = { + static const struct coef_fw coef0255[] = { WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */ WRITE_COEF(0x1b, 0x0c2b), WRITE_COEFEX(0x57, 0x03, 0x8ea6), {} }; - static struct coef_fw coef0256[] = { + static const struct coef_fw coef0256[] = { WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */ WRITE_COEF(0x1b, 0x0e6b), {} }; - static struct coef_fw coef0233[] = { + static const struct coef_fw coef0233[] = { WRITE_COEF(0x45, 0xe429), WRITE_COEF(0x1b, 0x0c2b), WRITE_COEF(0x32, 0x4ea3), {} }; - static struct coef_fw coef0288[] = { + static const struct coef_fw coef0288[] = { UPDATE_COEF(0x50, 0x2000, 0x2000), UPDATE_COEF(0x56, 0x0006, 0x0006), UPDATE_COEF(0x66, 0x0008, 0), UPDATE_COEF(0x67, 0x2000, 0), {} }; - static struct coef_fw coef0292[] = { + static const struct coef_fw coef0292[] = { WRITE_COEF(0x6b, 0xe429), WRITE_COEF(0x76, 0x0008), WRITE_COEF(0x18, 0x7388), {} }; - static struct coef_fw coef0293[] = { + static const struct coef_fw coef0293[] = { WRITE_COEF(0x45, 0xe429), /* Set to omtp type */ UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */ {} }; - static struct coef_fw coef0688[] = { + static const struct coef_fw coef0688[] = { WRITE_COEF(0x11, 0x0001), WRITE_COEF(0x15, 0x0d50), WRITE_COEF(0xc3, 0x0000), {} }; - static struct coef_fw coef0225[] = { + static const struct coef_fw coef0225[] = { UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10), UPDATE_COEF(0x63, 3<<14, 2<<14), {} @@ -4802,17 +4803,17 @@ static void alc_determine_headset_type(struct hda_codec *codec) int val; bool is_ctia = false; struct alc_spec *spec = codec->spec; - static struct coef_fw coef0255[] = { + static const struct coef_fw coef0255[] = { WRITE_COEF(0x45, 0xd089), /* combo jack auto switch control(Check type)*/ WRITE_COEF(0x49, 0x0149), /* combo jack auto switch control(Vref conteol) */ {} }; - static struct coef_fw coef0288[] = { + static const struct coef_fw coef0288[] = { UPDATE_COEF(0x4f, 0xfcc0, 0xd400), /* Check Type */ {} }; - static struct coef_fw coef0298[] = { + static const struct coef_fw coef0298[] = { UPDATE_COEF(0x50, 0x2000, 0x2000), UPDATE_COEF(0x56, 0x0006, 0x0006), UPDATE_COEF(0x66, 0x0008, 0), @@ -4820,19 +4821,19 @@ static void alc_determine_headset_type(struct hda_codec *codec) UPDATE_COEF(0x19, 0x1300, 0x1300), {} }; - static struct coef_fw coef0293[] = { + static const struct coef_fw coef0293[] = { UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */ WRITE_COEF(0x45, 0xD429), /* Set to ctia type */ {} }; - static struct coef_fw coef0688[] = { + static const struct coef_fw coef0688[] = { WRITE_COEF(0x11, 0x0001), WRITE_COEF(0xb7, 0x802b), WRITE_COEF(0x15, 0x0d60), WRITE_COEF(0xc3, 0x0c00), {} }; - static struct coef_fw coef0274[] = { + static const struct coef_fw coef0274[] = { UPDATE_COEF(0x4a, 0x0010, 0), UPDATE_COEF(0x4a, 0x8000, 0), WRITE_COEF(0x45, 0xd289), @@ -5119,7 +5120,7 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec, static void alc255_set_default_jack_type(struct hda_codec *codec) { /* Set to iphone type */ - static struct coef_fw alc255fw[] = { + static const struct coef_fw alc255fw[] = { WRITE_COEF(0x1b, 0x880b), WRITE_COEF(0x45, 0xd089), WRITE_COEF(0x1b, 0x080b), @@ -5127,7 +5128,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec) WRITE_COEF(0x1b, 0x0c0b), {} }; - static struct coef_fw alc256fw[] = { + static const struct coef_fw alc256fw[] = { WRITE_COEF(0x1b, 0x884b), WRITE_COEF(0x45, 0xd089), WRITE_COEF(0x1b, 0x084b), @@ -5920,7 +5921,8 @@ enum { ALC289_FIXUP_DUAL_SPK, ALC294_FIXUP_SPK2_TO_DAC1, ALC294_FIXUP_ASUS_DUAL_SPK, - + ALC285_FIXUP_THINKPAD_HEADSET_JACK, + ALC294_FIXUP_ASUS_HPE, }; static const struct hda_fixup alc269_fixups[] = { @@ -6684,6 +6686,8 @@ static const struct hda_fixup alc269_fixups[] = { [ALC285_FIXUP_SPEAKER2_TO_DAC1] = { .type = HDA_FIXUP_FUNC, .v.func = alc285_fixup_speaker2_to_dac1, + .chained = true, + .chain_id = ALC269_FIXUP_THINKPAD_ACPI }, [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = { .type = HDA_FIXUP_PINS, @@ -7040,7 +7044,23 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC294_FIXUP_SPK2_TO_DAC1 }, - + [ALC285_FIXUP_THINKPAD_HEADSET_JACK] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_headset_jack, + .chained = true, + .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1 + }, + [ALC294_FIXUP_ASUS_HPE] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* Set EAPD high */ + { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x7774 }, + { } + }, + .chained = true, + .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -7115,6 +7135,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x098d, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x09bf, "Dell Precision", ALC233_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), @@ -7204,6 +7226,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), @@ -7274,8 +7297,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), - SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1), - SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1), + SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), + SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), @@ -8057,6 +8080,8 @@ static int patch_alc269(struct hda_codec *codec) spec->gen.mixer_nid = 0; break; case 0x10ec0225: + codec->power_save_node = 1; + /* fall through */ case 0x10ec0295: case 0x10ec0299: spec->codec_variant = ALC269_TYPE_ALC225; @@ -8519,7 +8544,30 @@ static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec, } } -static struct coef_fw alc668_coefs[] = { +static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + static const struct hda_pintbl pincfgs[] = { + { 0x19, 0x02a11040 }, /* use as headset mic, with its own jack detect */ + { 0x1b, 0x0181304f }, + { } + }; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + spec->gen.mixer_nid = 0; + spec->parse_flags |= HDA_PINCFG_HEADSET_MIC; + snd_hda_apply_pincfgs(codec, pincfgs); + break; + case HDA_FIXUP_ACT_INIT: + alc_write_coef_idx(codec, 0x19, 0xa054); + break; + } +} + +static const struct coef_fw alc668_coefs[] = { WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b, 0x0), @@ -8592,6 +8640,9 @@ enum { ALC662_FIXUP_LENOVO_MULTI_CODECS, ALC669_FIXUP_ACER_ASPIRE_ETHOS, ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET, + ALC671_FIXUP_HP_HEADSET_MIC2, + ALC662_FIXUP_ACER_X2660G_HEADSET_MODE, + ALC662_FIXUP_ACER_NITRO_HEADSET_MODE, }; static const struct hda_fixup alc662_fixups[] = { @@ -8933,6 +8984,29 @@ static const struct hda_fixup alc662_fixups[] = { .chained = true, .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET }, + [ALC671_FIXUP_HP_HEADSET_MIC2] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc671_fixup_hp_headset_mic2, + }, + [ALC662_FIXUP_ACER_X2660G_HEADSET_MODE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x1a, 0x02a1113c }, /* use as headset mic, without its own jack detect */ + { } + }, + .chained = true, + .chain_id = ALC662_FIXUP_USI_FUNC + }, + [ALC662_FIXUP_ACER_NITRO_HEADSET_MODE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */ + { 0x1b, 0x0221144f }, + { } + }, + .chained = true, + .chain_id = ALC662_FIXUP_USI_FUNC + }, }; static const struct snd_pci_quirk alc662_fixup_tbl[] = { @@ -8944,6 +9018,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), + SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE), + SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE), SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13), @@ -9115,6 +9191,23 @@ static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = { {0x12, 0x90a60130}, {0x14, 0x90170110}, {0x15, 0x0321101f}), + SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2, + {0x14, 0x01014010}, + {0x17, 0x90170150}, + {0x19, 0x02a11060}, + {0x1b, 0x01813030}, + {0x21, 0x02211020}), + SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2, + {0x14, 0x01014010}, + {0x18, 0x01a19040}, + {0x1b, 0x01813030}, + {0x21, 0x02211020}), + SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2, + {0x14, 0x01014020}, + {0x17, 0x90170110}, + {0x18, 0x01a19050}, + {0x1b, 0x01813040}, + {0x21, 0x02211030}), {} }; diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c index 861210f6bf4f..4cbef9affffd 100644 --- a/sound/soc/codecs/pcm512x.c +++ b/sound/soc/codecs/pcm512x.c @@ -1564,13 +1564,15 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) } pcm512x->sclk = devm_clk_get(dev, NULL); - if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) - return -EPROBE_DEFER; + if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err; + } if (!IS_ERR(pcm512x->sclk)) { ret = clk_prepare_enable(pcm512x->sclk); if (ret != 0) { dev_err(dev, "Failed to enable SCLK: %d\n", ret); - return ret; + goto err; } } diff --git a/sound/soc/intel/skylake/skl-debug.c b/sound/soc/intel/skylake/skl-debug.c index 3466675f2678..a15aa2ffa681 100644 --- a/sound/soc/intel/skylake/skl-debug.c +++ b/sound/soc/intel/skylake/skl-debug.c @@ -34,8 +34,8 @@ static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf, int i; ssize_t ret = 0; - for (i = 0; i < max_pin; i++) - ret += snprintf(buf + size, MOD_BUF - size, + for (i = 0; i < max_pin; i++) { + ret += scnprintf(buf + size, MOD_BUF - size, "%s %d\n\tModule %d\n\tInstance %d\n\t" "In-used %s\n\tType %s\n" "\tState %d\n\tIndex %d\n", @@ -45,13 +45,15 @@ static ssize_t skl_print_pins(struct skl_module_pin *m_pin, char *buf, m_pin[i].in_use ? "Used" : "Unused", m_pin[i].is_dynamic ? "Dynamic" : "Static", m_pin[i].pin_state, i); + size += ret; + } return ret; } static ssize_t skl_print_fmt(struct skl_module_fmt *fmt, char *buf, ssize_t size, bool direction) { - return snprintf(buf + size, MOD_BUF - size, + return scnprintf(buf + size, MOD_BUF - size, "%s\n\tCh %d\n\tFreq %d\n\tBit depth %d\n\t" "Valid bit depth %d\n\tCh config %#x\n\tInterleaving %d\n\t" "Sample Type %d\n\tCh Map %#x\n", @@ -75,16 +77,16 @@ static ssize_t module_read(struct file *file, char __user *user_buf, if (!buf) return -ENOMEM; - ret = snprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n" + ret = scnprintf(buf, MOD_BUF, "Module:\n\tUUID %pUL\n\tModule id %d\n" "\tInstance id %d\n\tPvt_id %d\n", mconfig->guid, mconfig->id.module_id, mconfig->id.instance_id, mconfig->id.pvt_id); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "Resources:\n\tCPC %#x\n\tIBS %#x\n\tOBS %#x\t\n", res->cpc, res->ibs, res->obs); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "Module data:\n\tCore %d\n\tIn queue %d\n\t" "Out queue %d\n\tType %s\n", mconfig->core_id, mconfig->max_in_queue, @@ -94,38 +96,38 @@ static ssize_t module_read(struct file *file, char __user *user_buf, ret += skl_print_fmt(mconfig->in_fmt, buf, ret, true); ret += skl_print_fmt(mconfig->out_fmt, buf, ret, false); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "Fixup:\n\tParams %#x\n\tConverter %#x\n", mconfig->params_fixup, mconfig->converter); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "Module Gateway:\n\tType %#x\n\tVbus %#x\n\tHW conn %#x\n\tSlot %#x\n", mconfig->dev_type, mconfig->vbus_id, mconfig->hw_conn_type, mconfig->time_slot); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "Pipeline:\n\tID %d\n\tPriority %d\n\tConn Type %d\n\t" "Pages %#x\n", mconfig->pipe->ppl_id, mconfig->pipe->pipe_priority, mconfig->pipe->conn_type, mconfig->pipe->memory_pages); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "\tParams:\n\t\tHost DMA %d\n\t\tLink DMA %d\n", mconfig->pipe->p_params->host_dma_id, mconfig->pipe->p_params->link_dma_id); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "\tPCM params:\n\t\tCh %d\n\t\tFreq %d\n\t\tFormat %d\n", mconfig->pipe->p_params->ch, mconfig->pipe->p_params->s_freq, mconfig->pipe->p_params->s_fmt); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "\tLink %#x\n\tStream %#x\n", mconfig->pipe->p_params->linktype, mconfig->pipe->p_params->stream); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "\tState %d\n\tPassthru %s\n", mconfig->pipe->state, mconfig->pipe->passthru ? "true" : "false"); @@ -135,7 +137,7 @@ static ssize_t module_read(struct file *file, char __user *user_buf, ret += skl_print_pins(mconfig->m_out_pin, buf, mconfig->max_out_queue, ret, false); - ret += snprintf(buf + ret, MOD_BUF - ret, + ret += scnprintf(buf + ret, MOD_BUF - ret, "Other:\n\tDomain %d\n\tHomogeneous Input %s\n\t" "Homogeneous Output %s\n\tIn Queue Mask %d\n\t" "Out Queue Mask %d\n\tDMA ID %d\n\tMem Pages %d\n\t" @@ -191,7 +193,7 @@ static ssize_t fw_softreg_read(struct file *file, char __user *user_buf, __ioread32_copy(d->fw_read_buff, fw_reg_addr, w0_stat_sz >> 2); for (offset = 0; offset < FW_REG_SIZE; offset += 16) { - ret += snprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset); + ret += scnprintf(tmp + ret, FW_REG_BUF - ret, "%#.4x: ", offset); hex_dump_to_buffer(d->fw_read_buff + offset, 16, 16, 4, tmp + ret, FW_REG_BUF - ret, 0); ret += strlen(tmp + ret); diff --git a/sound/soc/intel/skylake/skl-ssp-clk.c b/sound/soc/intel/skylake/skl-ssp-clk.c index 1c0e5226cb5b..bd43885f3805 100644 --- a/sound/soc/intel/skylake/skl-ssp-clk.c +++ b/sound/soc/intel/skylake/skl-ssp-clk.c @@ -384,9 +384,11 @@ static int skl_clk_dev_probe(struct platform_device *pdev) &clks[i], clk_pdata, i); if (IS_ERR(data->clk[data->avail_clk_cnt])) { - ret = PTR_ERR(data->clk[data->avail_clk_cnt++]); + ret = PTR_ERR(data->clk[data->avail_clk_cnt]); goto err_unreg_skl_clk; } + + data->avail_clk_cnt++; } platform_set_drvdata(pdev, data); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a63537fda85c..70adc95e83ef 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -4761,7 +4761,7 @@ static void soc_dapm_shutdown_dapm(struct snd_soc_dapm_context *dapm) continue; if (w->power) { dapm_seq_insert(w, &down_list, false); - w->power = 0; + w->new_power = 0; powerdown = 1; } } diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 24d61d8e7cc4..f1f5e3ea4fb6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -3602,16 +3602,16 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, unsigned long flags; /* FE state */ - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "[%s - %s]\n", fe->dai_link->name, stream ? "Capture" : "Playback"); - offset += snprintf(buf + offset, size - offset, "State: %s\n", + offset += scnprintf(buf + offset, size - offset, "State: %s\n", dpcm_state_string(fe->dpcm[stream].state)); if ((fe->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && (fe->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "Hardware Params: " "Format = %s, Channels = %d, Rate = %d\n", snd_pcm_format_name(params_format(params)), @@ -3619,10 +3619,10 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, params_rate(params)); /* BEs state */ - offset += snprintf(buf + offset, size - offset, "Backends:\n"); + offset += scnprintf(buf + offset, size - offset, "Backends:\n"); if (list_empty(&fe->dpcm[stream].be_clients)) { - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " No active DSP links\n"); goto out; } @@ -3632,16 +3632,16 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe, struct snd_soc_pcm_runtime *be = dpcm->be; params = &dpcm->hw_params; - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, "- %s\n", be->dai_link->name); - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " State: %s\n", dpcm_state_string(be->dpcm[stream].state)); if ((be->dpcm[stream].state >= SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state <= SND_SOC_DPCM_STATE_STOP)) - offset += snprintf(buf + offset, size - offset, + offset += scnprintf(buf + offset, size - offset, " Hardware Params: " "Format = %s, Channels = %d, Rate = %d\n", snd_pcm_format_name(params_format(params)), diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index d00203ef8305..b19ecaf0febf 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -2320,8 +2320,11 @@ static int soc_tplg_link_elems_load(struct soc_tplg *tplg, } ret = soc_tplg_link_config(tplg, _link); - if (ret < 0) + if (ret < 0) { + if (!abi_match) + kfree(_link); return ret; + } /* offset by version-specific struct size and * real priv data size @@ -2485,7 +2488,7 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, { struct snd_soc_tplg_manifest *manifest, *_manifest; bool abi_match; - int err; + int ret = 0; if (tplg->pass != SOC_TPLG_PASS_MANIFEST) return 0; @@ -2498,19 +2501,19 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, _manifest = manifest; } else { abi_match = false; - err = manifest_new_ver(tplg, manifest, &_manifest); - if (err < 0) - return err; + ret = manifest_new_ver(tplg, manifest, &_manifest); + if (ret < 0) + return ret; } /* pass control to component driver for optional further init */ if (tplg->comp && tplg->ops && tplg->ops->manifest) - return tplg->ops->manifest(tplg->comp, tplg->index, _manifest); + ret = tplg->ops->manifest(tplg->comp, tplg->index, _manifest); if (!abi_match) /* free the duplicated one */ kfree(_manifest); - return 0; + return ret; } /* validate header magic, size and type */ diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 8984d965037d..e7b1a80e2a14 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -497,7 +497,7 @@ int snd_sof_ipc_stream_posn(struct snd_sof_dev *sdev, /* send IPC to the DSP */ err = sof_ipc_tx_message(sdev->ipc, - stream.hdr.cmd, &stream, sizeof(stream), &posn, + stream.hdr.cmd, &stream, sizeof(stream), posn, sizeof(*posn)); if (err < 0) { dev_err(sdev->dev, "error: failed to get stream %d position\n", diff --git a/sound/soc/sprd/Kconfig b/sound/soc/sprd/Kconfig index 5474fd3de8c0..5e0ac8278572 100644 --- a/sound/soc/sprd/Kconfig +++ b/sound/soc/sprd/Kconfig @@ -8,7 +8,7 @@ config SND_SOC_SPRD the Spreadtrum SoCs' Audio interfaces. config SND_SOC_SPRD_MCDT - bool "Spreadtrum multi-channel data transfer support" + tristate "Spreadtrum multi-channel data transfer support" depends on SND_SOC_SPRD help Say y here to enable multi-channel data transfer support. It diff --git a/sound/soc/sprd/sprd-mcdt.h b/sound/soc/sprd/sprd-mcdt.h index 9cc7e207ac76..679e3af3baad 100644 --- a/sound/soc/sprd/sprd-mcdt.h +++ b/sound/soc/sprd/sprd-mcdt.h @@ -48,7 +48,7 @@ struct sprd_mcdt_chan { struct list_head list; }; -#ifdef CONFIG_SND_SOC_SPRD_MCDT +#if IS_ENABLED(CONFIG_SND_SOC_SPRD_MCDT) struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel, enum sprd_mcdt_channel_type type); void sprd_mcdt_free_chan(struct sprd_mcdt_chan *chan); diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 30bcd5d3a32a..10eb4b8e8e7e 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1543,20 +1543,20 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) return ret; } - ret = devm_snd_soc_register_component(&pdev->dev, &stm32_component, - &sai->cpu_dai_drv, 1); + ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0); + if (ret) { + dev_err(&pdev->dev, "Could not register pcm dma\n"); + return ret; + } + + ret = snd_soc_register_component(&pdev->dev, &stm32_component, + &sai->cpu_dai_drv, 1); if (ret) return ret; if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) conf = &stm32_sai_pcm_config_spdif; - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, conf, 0); - if (ret) { - dev_err(&pdev->dev, "Could not register pcm dma\n"); - return ret; - } - return 0; } @@ -1565,6 +1565,8 @@ static int stm32_sai_sub_remove(struct platform_device *pdev) struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev); clk_unprepare(sai->pdata->pclk); + snd_dmaengine_pcm_unregister(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); return 0; } diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index b5a3f754a4f1..4f096685ed65 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -305,7 +305,7 @@ static void line6_data_received(struct urb *urb) line6_midibuf_read(mb, line6->buffer_message, LINE6_MIDI_MESSAGE_MAXLEN); - if (done == 0) + if (done <= 0) break; line6->message_length = done; diff --git a/sound/usb/line6/midibuf.c b/sound/usb/line6/midibuf.c index 8d6eefa0d936..6a70463f82c4 100644 --- a/sound/usb/line6/midibuf.c +++ b/sound/usb/line6/midibuf.c @@ -159,7 +159,7 @@ int line6_midibuf_read(struct midi_buffer *this, unsigned char *data, int midi_length_prev = midibuf_message_length(this->command_prev); - if (midi_length_prev > 0) { + if (midi_length_prev > 1) { midi_length = midi_length_prev - 1; repeat = 1; } else diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 7902a5681fc8..b8fc7d972be9 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -35,7 +35,7 @@ endif # Only pass canonical directory names as the output directory: # ifneq ($(O),) - FULL_O := $(shell readlink -f $(O) || echo $(O)) + FULL_O := $(shell cd $(PWD); readlink -f $(O) || echo $(O)) endif # diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c index ede040cf82ad..20e9a189ad92 100644 --- a/tools/perf/arch/arm/util/cs-etm.c +++ b/tools/perf/arch/arm/util/cs-etm.c @@ -865,9 +865,12 @@ static int cs_etm_read_finish(struct auxtrace_record *itr, int idx) struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { - if (evsel->core.attr.type == ptr->cs_etm_pmu->type) + if (evsel->core.attr.type == ptr->cs_etm_pmu->type) { + if (evsel->disabled) + return 0; return perf_evlist__enable_event_idx(ptr->evlist, evsel, idx); + } } return -EINVAL; diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c index eba6541ec0f1..1d993c27242b 100644 --- a/tools/perf/arch/arm64/util/arm-spe.c +++ b/tools/perf/arch/arm64/util/arm-spe.c @@ -165,9 +165,12 @@ static int arm_spe_read_finish(struct auxtrace_record *itr, int idx) struct evsel *evsel; evlist__for_each_entry(sper->evlist, evsel) { - if (evsel->core.attr.type == sper->arm_spe_pmu->type) + if (evsel->core.attr.type == sper->arm_spe_pmu->type) { + if (evsel->disabled) + return 0; return perf_evlist__enable_event_idx(sper->evlist, evsel, idx); + } } return -EINVAL; } diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index f7f68a50a5cd..85799b5fa01d 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -415,9 +415,12 @@ static int intel_bts_read_finish(struct auxtrace_record *itr, int idx) struct evsel *evsel; evlist__for_each_entry(btsr->evlist, evsel) { - if (evsel->core.attr.type == btsr->intel_bts_pmu->type) + if (evsel->core.attr.type == btsr->intel_bts_pmu->type) { + if (evsel->disabled) + return 0; return perf_evlist__enable_event_idx(btsr->evlist, evsel, idx); + } } return -EINVAL; } diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index d6d26256915f..d43f9dec6998 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -1099,9 +1099,12 @@ static int intel_pt_read_finish(struct auxtrace_record *itr, int idx) struct evsel *evsel; evlist__for_each_entry(ptr->evlist, evsel) { - if (evsel->core.attr.type == ptr->intel_pt_pmu->type) + if (evsel->core.attr.type == ptr->intel_pt_pmu->type) { + if (evsel->disabled) + return 0; return perf_evlist__enable_event_idx(ptr->evlist, evsel, idx); + } } return -EINVAL; } diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c index df810096abfe..58906e9499bb 100644 --- a/tools/perf/bench/futex-wake.c +++ b/tools/perf/bench/futex-wake.c @@ -43,7 +43,7 @@ static bool done = false, silent = false, fshared = false; static pthread_mutex_t thread_lock; static pthread_cond_t thread_parent, thread_worker; static struct stats waketime_stats, wakeup_stats; -static unsigned int ncpus, threads_starting, nthreads = 0; +static unsigned int threads_starting, nthreads = 0; static int futex_flag = 0; static const struct option options[] = { @@ -141,7 +141,7 @@ int bench_futex_wake(int argc, const char **argv) sigaction(SIGINT, &act, NULL); if (!nthreads) - nthreads = ncpus; + nthreads = cpu->nr; worker = calloc(nthreads, sizeof(*worker)); if (!worker) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index eec9b282c047..4b07b1cc22dc 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -90,7 +90,7 @@ static inline bool replace_android_lib(const char *filename, char *newfilename) return true; } - if (!strncmp(filename, "/system/lib/", 11)) { + if (!strncmp(filename, "/system/lib/", 12)) { char *ndk, *app; const char *arch; size_t ndk_length; diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c index b659466ea498..bf50f464234f 100644 --- a/tools/perf/util/probe-file.c +++ b/tools/perf/util/probe-file.c @@ -206,6 +206,9 @@ static struct strlist *__probe_file__get_namelist(int fd, bool include_group) } else ret = strlist__add(sl, tev.event); clear_probe_trace_event(&tev); + /* Skip if there is same name multi-probe event in the list */ + if (ret == -EEXIST) + ret = 0; if (ret < 0) break; } diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 9ecea45da4ca..aaf3b24fffa4 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -615,14 +615,19 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, return -EINVAL; } - /* Try to get actual symbol name from symtab */ - symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); + if (dwarf_entrypc(sp_die, &eaddr) == 0) { + /* If the DIE has entrypc, use it. */ + symbol = dwarf_diename(sp_die); + } else { + /* Try to get actual symbol name and address from symtab */ + symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); + eaddr = sym.st_value; + } if (!symbol) { pr_warning("Failed to find symbol at 0x%lx\n", (unsigned long)paddr); return -ENOENT; } - eaddr = sym.st_value; tp->offset = (unsigned long)(paddr - eaddr); tp->address = (unsigned long)paddr; diff --git a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c index 3f893b99b337..555cb338a71a 100644 --- a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c +++ b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c @@ -82,7 +82,7 @@ static struct pci_access *pci_acc; static struct pci_dev *amd_fam14h_pci_dev; static int nbp1_entered; -struct timespec start_time; +static struct timespec start_time; static unsigned long long timediff; #ifdef DEBUG diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c index f634aeb65c5f..7fb4f7a291ad 100644 --- a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c +++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c @@ -19,7 +19,7 @@ struct cpuidle_monitor cpuidle_sysfs_monitor; static unsigned long long **previous_count; static unsigned long long **current_count; -struct timespec start_time; +static struct timespec start_time; static unsigned long long timediff; static int cpuidle_get_count_percent(unsigned int id, double *percent, diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c index d3c3e6e7aa26..3d54fd433626 100644 --- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c +++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c @@ -27,6 +27,8 @@ struct cpuidle_monitor *all_monitors[] = { 0 }; +int cpu_count; + static struct cpuidle_monitor *monitors[MONITORS_MAX]; static unsigned int avail_monitors; diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h index a2d901d3bfaf..eafef38f1982 100644 --- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h +++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h @@ -25,7 +25,7 @@ #endif #define CSTATE_DESC_LEN 60 -int cpu_count; +extern int cpu_count; /* Hard to define the right names ...: */ enum power_range_e { diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index ded7a950dc40..6d2f3a1b2249 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 ifneq ($(O),) ifeq ($(origin O), command line) - dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),) - ABSOLUTE_O := $(shell cd $(O) ; pwd) + dummy := $(if $(shell cd $(PWD); test -d $(O) || echo $(O)),$(error O=$(O) does not exist),) + ABSOLUTE_O := $(shell cd $(PWD); cd $(O) ; pwd) OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/) COMMAND_O := O=$(ABSOLUTE_O) ifeq ($(objtree),) diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 220d04f958a6..42b6cd41d2ea 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1383,7 +1383,7 @@ sub reboot { } else { # Make sure everything has been written to disk - run_ssh("sync"); + run_ssh("sync", 10); if (defined($time)) { start_monitor; diff --git a/tools/testing/selftests/filesystems/incfs/incfs_test.c b/tools/testing/selftests/filesystems/incfs/incfs_test.c index 9bfb271628a8..723f9cbd15bc 100644 --- a/tools/testing/selftests/filesystems/incfs/incfs_test.c +++ b/tools/testing/selftests/filesystems/incfs/incfs_test.c @@ -25,8 +25,6 @@ #include "lz4.h" #include "utils.h" -#define __packed __attribute__((__packed__)) - #define TEST_FAILURE 1 #define TEST_SUCCESS 0 #define INCFS_MAX_MTREE_LEVELS 8 @@ -69,101 +67,6 @@ struct linux_dirent64 { char d_name[0]; } __packed; -/* - * The certificate below and the private key were created by calling: - * openssl req -x509 -newkey rsa:4096 -keyout private.key -out cert.crt - * -days 1000 -sha256 -nodes -outform PEM -subj - * "/C=US/ST=WA/L=Kirkland/O=Example/OU=Org/CN=www.example.com" - */ -char x509_cert[] = -"-----BEGIN CERTIFICATE-----\n" -"MIIFvzCCA6egAwIBAgIUXpwqelEljm6BBllRQGHLrls2MYgwDQYJKoZIhvcNAQEL\n" -"BQAwbzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xETAPBgNVBAcM\n" -"CEtpcmtsYW5kMRAwDgYDVQQKDAdFeGFtcGxlMQwwCgYDVQQLDANPcmcxGDAWBgNV\n" -"BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xOTA4MDgyMzA3MDZaFw0yMjA1MDQyMzA3\n" -"MDZaMG8xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMREwDwYDVQQH\n" -"DAhLaXJrbGFuZDEQMA4GA1UECgwHRXhhbXBsZTEMMAoGA1UECwwDT3JnMRgwFgYD\n" -"VQQDDA93d3cuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n" -"AoICAQC1LuFW/lDV/GflqFMz7RDvFFgWld982ZuDJRaK55JNj+MI4RZNL61PDw43\n" -"NeeJtqUoVxSLS9wHURjSjD/CV5GudUOnzGfbwFlLko+jhYRT4HNFS+5ys1FEJLtA\n" -"uYcY4P9GHQEXYUX+ue82A2kJ91oY6G3vCQYJFiGteb6TRDICmug31x4pBfB8rOdt\n" -"4/NXS/Dn+S0/mJlxw34IKfqrlFjzUziRZtAWWqDcfxFDUizSggkdXIUq4GY38RAD\n" -"qGewNNCab3ClJDP7/M32BhSNgsIKhgtSTM2+ocfvBhwup+BjV6UbL21DPAshlolV\n" -"gSL1HM2jin5bi4bpFMreY0LXwFih87/6AVSfQHY9TZrombVZnMxvB7NG1NCSwDBT\n" -"qjjFb3oiSMugJzY+MhISM754m46fwUyHZ1ylWCLJEU8kQ5A1q9vvqMcaDa4uTGP3\n" -"UgC6SyVmZxG2o+AO6m8TRTCtqHN41mPTM9HK4T1UyuzVpykSc2LlYkKE517SyEiV\n" -"XDmotNb2myXNYHHTjRYNxkq75Lbii2I4Q4z8XtDngaIrhZqACKSqIt2CocGjx61S\n" -"oxKWi+LGa7B4NaCMjz1LnaOIsXn1rJDRnUWL49T42g4kOi/5QaC2JDygfefw1hAb\n" -"uxkq9EYUDg+w9broltiBf4rKAnw8JMySARnyPZbj0lhZK3va5wIDAQABo1MwUTAd\n" -"BgNVHQ4EFgQUo6JN3gY2yGbzOTNj8Al7hNB3rw0wHwYDVR0jBBgwFoAUo6JN3gY2\n" -"yGbzOTNj8Al7hNB3rw0wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n" -"AgEAQb3pJqOzM4whfNVdpEOswd1EApcWNM1ps9iTlEEjDoRv9F7F1PW0uXCIpk3B\n" -"j5JgCmIxAcPnzj42rduRSx421hHMZhbAIWI/JL4ZSF64qlG0YrmJDXlJgSMoyst5\n" -"biUqeWgO7Js5udPt3zhkeA62z3hGM6dE5B3k7gHTaKKtK17+UeR9imZKsOK8GBnM\n" -"rxMPI6XghxxAK2OQ/r09DHDiyf/GxgOE46oknfXfMPx3HaSvDKrZUTZ+UvVbM5c2\n" -"5eXOgH5UO/e4llLknJK7CoP/R6G7pV44iT4t4t9FMnvCYvavAHwfR+6z5vTF3o8a\n" -"wd80fC8z1vfLsIPLROdzBl9rGCvv536fPiEA677CM1AZkjfT0a9DVzrE1NDvuCUF\n" -"0KgEdiNwux+hO6dbTyiS38yPT6TbpoWJptJmFhFkC4hGvUgoX/TI0covSyf74VRH\n" -"k3BHojOBMYiX1K66xoN7fhlGK8cith3L0XXPB8CgSEUPWURvm8RCaGuX2T3FZomF\n" -"BCnNpN+WNnN3Yf4OkjtuvtxxktUU7pfVLsUxrdpo/ph4rWm6U83VT/Zlq92aF4vW\n" -"QJ+7uraQFip7e+Gy9g3UJINm3B7b1C4ch/Z/upCZESOI/23sVGzkfTgOrS+23i6/\n" -"Vi9YW75zySC2FCa1AWMS1NmS5qfDSycJUgD6YvOUg0C54ZI=\n" -"-----END CERTIFICATE-----"; - -char private_key[] = -"-----BEGIN PRIVATE KEY-----\n" -"MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQC1LuFW/lDV/Gfl\n" -"qFMz7RDvFFgWld982ZuDJRaK55JNj+MI4RZNL61PDw43NeeJtqUoVxSLS9wHURjS\n" -"jD/CV5GudUOnzGfbwFlLko+jhYRT4HNFS+5ys1FEJLtAuYcY4P9GHQEXYUX+ue82\n" -"A2kJ91oY6G3vCQYJFiGteb6TRDICmug31x4pBfB8rOdt4/NXS/Dn+S0/mJlxw34I\n" -"KfqrlFjzUziRZtAWWqDcfxFDUizSggkdXIUq4GY38RADqGewNNCab3ClJDP7/M32\n" -"BhSNgsIKhgtSTM2+ocfvBhwup+BjV6UbL21DPAshlolVgSL1HM2jin5bi4bpFMre\n" -"Y0LXwFih87/6AVSfQHY9TZrombVZnMxvB7NG1NCSwDBTqjjFb3oiSMugJzY+MhIS\n" -"M754m46fwUyHZ1ylWCLJEU8kQ5A1q9vvqMcaDa4uTGP3UgC6SyVmZxG2o+AO6m8T\n" -"RTCtqHN41mPTM9HK4T1UyuzVpykSc2LlYkKE517SyEiVXDmotNb2myXNYHHTjRYN\n" -"xkq75Lbii2I4Q4z8XtDngaIrhZqACKSqIt2CocGjx61SoxKWi+LGa7B4NaCMjz1L\n" -"naOIsXn1rJDRnUWL49T42g4kOi/5QaC2JDygfefw1hAbuxkq9EYUDg+w9broltiB\n" -"f4rKAnw8JMySARnyPZbj0lhZK3va5wIDAQABAoICAQCMKul/0J2e/ncub6t2t4dr\n" -"PnTrfCT6xKqPqciny4Ee6hr9So1jR2gvink380bd/mQFMmEdZqGhM3cdpAzLf82f\n" -"hu7BSNxsYIF0er0PB4MZFMJ4sMaXC+zp5/TJnP5MG/zBND0c5k8tQpEyWy8O28Jj\n" -"FKW/0F5P90Q0ncP20EJUS50tXgniOMsU2Prtw/UE6yZDgD0mPxsurMu66ycXSFwM\n" -"WqyfqEeBk7lw/AjR6Sft71W31lTbl+DclG0MN2OIKUPcxiwCRmDFKI36MDgERk1x\n" -"sMPfdrWRLj2ryDFTUuLAWBTOVEGWS0RdRsWWVaJCuHbKd6FLl0TW2xQbOfWDTjYC\n" -"Ps31ejh163qdbk7OGOZIbd83fP3jsyL+4eNzhUpeXMKhfG58mFIv4yhdZIUOpuL6\n" -"aqnoU9z9wEsJKj/SrKr3nw6tuTnmbXgNjun9LfTFmqqDRBYd0Okiprw6jHNM1jgA\n" -"GG0kC/K7r89jKymVDABwGMFCS33ynR1Tb6zG+cqgNMPw19Fy3uQuW21CjqSzCOyP\n" -"aEVCEUZeP+ofql5+7ZKi6Dj+EdTfeKt2ihgheHZZoaYSINb8tsnKbdJhwBfW9PFT\n" -"aT/hu3bnO2FPC8H2NGOqxOEeel9ALU4SFu1pOknEhiL3/mNfOQ+KgrSRDtNRlcL0\n" -"cto05J90u0cmqwWKlshfaQKCAQEA5dcklxs4ezyzt28NcsiyS02oZ+9TkQp6pCXV\n" -"kx7AwhivAmVTlJ+c6BegA5EPd7A1gknM3+EKzGpoBOqmlF45G57phVIAphAp4oCH\n" -"UOVtIQgM8p4EU2gtX+uNOopdYlpBQnWimXaHA2sOD9/yTbZ03j/McRH6D15+iCld\n" -"3880GHdZaYYbQmHoSDg39LRRO1bdS3WC0oKBD2gPi3K0b9RaZSwKzuVrmlvrLURj\n" -"WMZfmkGl4BsITfuoTxbWFVncG3Kb9eYkYUFZy4M2G/s849PS/HjrN7BvgpanjtVp\n" -"1/39APQfAYfUuBPbKYnb6F8dE0pb5cVd4uMZklAeTb3bXjOO9QKCAQEAyc4CxWXr\n" -"bG6Do5dGpWudQ7ucq00MR0T3MHQIu5XTn6BsPHAJ9ZgrQw9C24PXm2VEjjsrMs5T\n" -"rHNF9oeO39s25Za1iyJ+893icqA3h3ivCUOOoVE54BkuJK6REhkXPD5G1ubmxeBz\n" -"MKNehlpd/eSbJJArkzKFZ8sBtLt8i9VFhRnXSpDAbiMpCbjW+bem9MWdLmkenSnu\n" -"OUbnqYcJhFBCvOT7ZCHFCDNUNPfHcaReSY2EYjw0ZqtqAZD0Q+DL+RkLz7l1+/bF\n" -"eEwNjmjFTcwRyawqf38D4miU0H6ca16FkeSlbmM5p3HdwZK2HVYYz3FSwhox6Ebd\n" -"n6in42qfL4Ug6wKCAQAh9IDRWhIkErmyNdPUy1WbzmM8x5ye5t9rdLNywq5TfnYM\n" -"co/AezwhBax8GmgglIWzM9fykzqXLHklkMz/SlRBgl6ZdZ3m6qhlb/uNtfdDU/8l\n" -"sLaO4+sgKpp4tYxKRW8ytFJLPbmAhcZUDg+r73KgiuhXJAK/VoR29TWLJP9bRfaN\n" -"omRQkEpSsQuDOUhu7cxPo5KqKuGKNyNkxJNnmgWowLLwEfCtozrBO0M6EER7c4tf\n" -"6l51tuIMnSEPknD0FSB5WYCyZYcwi7fotlsuhVK8PdjyJzyyHDOw5FJ4uGsyQt55\n" -"yWlhsH1GS7mTQMn42Zlt/pR6OnbCqNdxQMUxy4gpAoIBAFvMbs5E0pb8nr0n72cI\n" -"UP2itl3mKpOw95D+94n9WcrfOt0zShSCKAvVQWCB1O5HXqwklj4CRWXI+iZu+7sx\n" -"CQPfTq3//ygH4x6paxkg+N6J8LPJMz6Rtb/R+QP2je9FlQvk9U1GEKArcLBFI0R/\n" -"XWOAgZHwBWd1nU0NjFY/qeQmIR02Q5LWQ7C8eG4X8MafriSShO6RSGCdtHwVhWq+\n" -"59ztfL3L7skQMFn37K3xS0LCMVpOcLfTeeFEgxjthVvG3OydPOJlGubiEbiaSEZf\n" -"cif/PUXKDYZMdIVzUsw0ryXykJ5qXKuizHFlv5oQtDCJKFBLgjBbLC2YluaIdekz\n" -"8gkCggEBAJWxS7EuB/qL7fOz0o3HRy0plR3qbwZ0pLoCz0Ii7WxraBS1yQwmxif1\n" -"Rgv89GyFqg1yQl3CSrMiw7oC9WxxxuiEZDO18c4KO3NTv9K4itN9OPQVBTHmEhod\n" -"KWcyP4/W/Sfuae77PyclSqUsAARRrKYn2fpLTS5ibaU0QZgHmdPgYDUrPr+6PHKK\n" -"ZfQKU2uBfuo6zoMbMmFi3UYG49j9rv4d6v+44vS1MPHV9JK/LD8YfBhgx8Pg/u6D\n" -"nUgipS48pkGjJr2u2Vu7Mx70vqz0Yf2neyyDbdLtkYauC4w7YKPTD0yzDJyGuAeB\n" -"GyPbW1yZa5vE302a1Cr0Cd7RC4AFAAw=\n" -"-----END PRIVATE KEY-----"; - struct test_files_set get_test_files_set(void) { static struct test_file files[] = { @@ -290,7 +193,7 @@ char *bin2hex(char *dst, const void *src, size_t count) return dst; } -static char *get_index_filename(char *mnt_dir, incfs_uuid_t id) +static char *get_index_filename(const char *mnt_dir, incfs_uuid_t id) { char path[FILENAME_MAX]; char str_id[1 + 2 * sizeof(id)]; @@ -301,15 +204,43 @@ static char *get_index_filename(char *mnt_dir, incfs_uuid_t id) return strdup(path); } -int open_file_by_id(char *mnt_dir, incfs_uuid_t id) +int open_file_by_id(const char *mnt_dir, incfs_uuid_t id, bool use_ioctl) { char *path = get_index_filename(mnt_dir, id); + int cmd_fd = open_commands_file(mnt_dir); int fd = open(path, O_RDWR); + struct incfs_permit_fill permit_fill = { + .file_descriptor = fd, + }; + int error = 0; - free(path); if (fd < 0) { print_error("Can't open file by id."); + error = -errno; + goto out; + } + + if (use_ioctl && ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) { + print_error("Failed to call PERMIT_FILL"); + error = -errno; + goto out; + } + + if (ioctl(fd, INCFS_IOC_PERMIT_FILL, &permit_fill) != -1 || + errno != EPERM) { + print_error( + "Successfully called PERMIT_FILL on non pending_read file"); return -errno; + goto out; + } + +out: + free(path); + close(cmd_fd); + + if (error) { + close(fd); + return error; } return fd; @@ -343,20 +274,18 @@ static int emit_test_blocks(char *mnt_dir, struct test_file *file, uint8_t *data_buf = malloc(data_buf_size); uint8_t *current_data = data_buf; uint8_t *data_end = data_buf + data_buf_size; - struct incfs_new_data_block *block_buf = - calloc(block_count, sizeof(*block_buf)); + struct incfs_fill_block *block_buf = + calloc(block_count, sizeof(struct incfs_fill_block)); + struct incfs_fill_blocks fill_blocks = { + .count = block_count, + .fill_blocks = ptr_to_u64(block_buf), + }; ssize_t write_res = 0; int fd; int error = 0; int i = 0; int blocks_written = 0; - fd = open_file_by_id(mnt_dir, file->id); - if (fd <= 0) { - error = -errno; - goto out; - } - for (i = 0; i < block_count; i++) { int block_index = blocks[i]; bool compress = (file->index + block_index) % 2 == 0; @@ -404,17 +333,33 @@ static int emit_test_blocks(char *mnt_dir, struct test_file *file, block_buf[i].block_index = block_index; block_buf[i].data_len = block_size; block_buf[i].data = ptr_to_u64(current_data); - block_buf[i].compression = - compress ? COMPRESSION_LZ4 : COMPRESSION_NONE; current_data += block_size; } if (!error) { - write_res = write(fd, block_buf, sizeof(*block_buf) * i); + fd = open_file_by_id(mnt_dir, file->id, false); + if (fd < 0) { + error = -errno; + goto out; + } + write_res = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); + if (write_res >= 0) { + ksft_print_msg("Wrote to file via normal fd error\n"); + error = -EPERM; + goto out; + } + + close(fd); + fd = open_file_by_id(mnt_dir, file->id, true); + if (fd < 0) { + error = -errno; + goto out; + } + write_res = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); if (write_res < 0) error = -errno; else - blocks_written = write_res / sizeof(*block_buf); + blocks_written = write_res; } if (error) { ksft_print_msg( @@ -720,8 +665,6 @@ static int build_mtree(struct test_file *file) int tree_lvl_index[INCFS_MAX_MTREE_LEVELS] = {}; int tree_lvl_count[INCFS_MAX_MTREE_LEVELS] = {}; int levels_count = 0; - char data_to_sign[256] = {}; - int sig_data_size; int i, level; if (file->size == 0) @@ -748,8 +691,9 @@ static int build_mtree(struct test_file *file) if (block_count == 1) { int seed = get_file_block_seed(file->index, 0); + memset(data, 0, INCFS_DATA_FILE_BLOCK_SIZE); rnd_buf((uint8_t *)data, file->size, seed); - sha256(data, file->size, file->root_hash); + sha256(data, INCFS_DATA_FILE_BLOCK_SIZE, file->root_hash); return 0; } @@ -764,11 +708,13 @@ static int build_mtree(struct test_file *file) int seed = get_file_block_seed(file->index, i); char *hash_ptr = file->mtree[block_index].data + block_off; - if (file->size - offset < block_size) + if (file->size - offset < block_size) { block_size = file->size - offset; + memset(data, 0, INCFS_DATA_FILE_BLOCK_SIZE); + } rnd_buf((uint8_t *)data, block_size, seed); - sha256(data, block_size, hash_ptr); + sha256(data, INCFS_DATA_FILE_BLOCK_SIZE, hash_ptr); } /* Build higher levels of hash tree. */ @@ -792,19 +738,6 @@ static int build_mtree(struct test_file *file) sha256(file->mtree[0].data, INCFS_DATA_FILE_BLOCK_SIZE, file->root_hash); - /* Calculating digital signature */ - snprintf(file->sig.add_data, sizeof(file->sig.add_data), "%ld", - file->size); - memcpy(data_to_sign, file->root_hash, SHA256_DIGEST_SIZE); - memcpy(data_to_sign + SHA256_DIGEST_SIZE, file->sig.add_data, - strlen(file->sig.add_data)); - sig_data_size = SHA256_DIGEST_SIZE + strlen(file->sig.add_data); - if (!sign_pkcs7(data_to_sign, sig_data_size, private_key, x509_cert, - &file->sig.data, &file->sig.size)) { - ksft_print_msg("Signing failed.\n"); - return -EINVAL; - } - return 0; } @@ -813,21 +746,21 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file) int err; int i; int fd; + struct incfs_fill_blocks fill_blocks = { + .count = file->mtree_block_count, + }; + struct incfs_fill_block *fill_block_array = + calloc(fill_blocks.count, sizeof(struct incfs_fill_block)); - size_t blocks_size = - file->mtree_block_count * sizeof(struct incfs_new_data_block); - struct incfs_new_data_block *blocks = NULL; - char *file_path; - - if (blocks_size == 0) + if (fill_blocks.count == 0) return 0; - blocks = malloc(blocks_size); - if (!blocks) + if (!fill_block_array) return -ENOMEM; + fill_blocks.fill_blocks = ptr_to_u64(fill_block_array); - for (i = 0; i < file->mtree_block_count; i++) { - blocks[i] = (struct incfs_new_data_block){ + for (i = 0; i < fill_blocks.count; i++) { + fill_block_array[i] = (struct incfs_fill_block){ .block_index = i, .data_len = INCFS_DATA_FILE_BLOCK_SIZE, .data = ptr_to_u64(file->mtree[i].data), @@ -835,18 +768,28 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file) }; } - file_path = concat_file_name(mount_dir, file->name); - fd = open(file_path, O_RDWR); - free(file_path); + fd = open_file_by_id(mount_dir, file->id, false); if (fd < 0) { err = errno; goto failure; } - err = write(fd, blocks, blocks_size); + err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); close(fd); + if (err >= 0) { + err = -EPERM; + goto failure; + } - if (err < blocks_size) + fd = open_file_by_id(mount_dir, file->id, true); + if (fd < 0) { + err = errno; + goto failure; + } + + err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); + close(fd); + if (err < fill_blocks.count) err = errno; else { err = 0; @@ -854,7 +797,7 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file) } failure: - free(blocks); + free(fill_block_array); return err; } @@ -1274,13 +1217,6 @@ static int dynamic_files_and_data_test(char *mount_dir) if (i == missing_file_idx) continue; - res = load_hash_tree(mount_dir, file); - if (res) { - ksft_print_msg("Can't load hashes for %s. error: %s\n", - file->name, strerror(-res)); - goto failure; - } - res = emit_test_file_data(mount_dir, file); if (res) { ksft_print_msg("Error %s emiting data for %s.\n", @@ -1479,7 +1415,6 @@ static int work_after_remount_test(char *mount_dir) /* Write first half of the data into the command file. (stage 1) */ for (i = 0; i < file_num_stage1; i++) { struct test_file *file = &test.files[i]; - int res; build_mtree(file); if (emit_file(cmd_fd, NULL, file->name, &file->id, @@ -1488,14 +1423,7 @@ static int work_after_remount_test(char *mount_dir) if (emit_test_file_data(mount_dir, file)) goto failure; - - res = load_hash_tree(mount_dir, file); - if (res) { - ksft_print_msg("Can't load hashes for %s. error: %s\n", - file->name, strerror(-res)); - goto failure; - } -} + } /* Unmount and mount again, to see that data is persistent. */ close(cmd_fd); @@ -1882,162 +1810,6 @@ failure: return TEST_FAILURE; } -static int signature_test(char *mount_dir) -{ - struct test_files_set test = get_test_files_set(); - const int file_num = test.files_count; - int i = 0; - unsigned char sig_buf[INCFS_MAX_SIGNATURE_SIZE]; - char *backing_dir; - int cmd_fd = -1; - - backing_dir = create_backing_dir(mount_dir); - if (!backing_dir) - goto failure; - - /* Mount FS and release the backing file. (10s wait time) */ - if (mount_fs(mount_dir, backing_dir, 10000) != 0) - goto failure; - - cmd_fd = open_commands_file(mount_dir); - if (cmd_fd < 0) - goto failure; - - /* Write hashes and data. */ - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - int res; - - build_mtree(file); - - res = crypto_emit_file(cmd_fd, NULL, file->name, &file->id, - file->size, file->root_hash, - file->sig.data, file->sig.size, file->sig.add_data); - - if (res) { - ksft_print_msg("Emit failed for %s. error: %s\n", - file->name, strerror(-res)); - goto failure; - } - - if (emit_test_file_data(mount_dir, file)) - goto failure; - - res = load_hash_tree(mount_dir, file); - if (res) { - ksft_print_msg("Can't load hashes for %s. error: %s\n", - file->name, strerror(-res)); - goto failure; - } - } - - /* Validate data */ - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - int sig_len; - char *path; - int fd; - - if (validate_test_file_content(mount_dir, file) < 0) - goto failure; - - path = concat_file_name(mount_dir, file->name); - fd = open(path, O_RDWR); - free(path); - if (fd < 0) { - print_error("Can't open file"); - goto failure; - } - - sig_len = get_file_signature(fd, sig_buf, ARRAY_SIZE(sig_buf)); - - if (close(fd)) { - print_error("Can't close file"); - goto failure; - } - - if (sig_len < 0) { - ksft_print_msg("Can't load signature %s. error: %s\n", - file->name, strerror(-sig_len)); - goto failure; - } - - if (sig_len != file->sig.size || - memcmp(sig_buf, file->sig.data, sig_len)) { - ksft_print_msg("Signature mismatch %s.\n", - file->name); - goto failure; - } - } - - /* Unmount and mount again, to make sure the signature is persistent. */ - close(cmd_fd); - cmd_fd = -1; - if (umount(mount_dir) != 0) { - print_error("Can't unmout FS"); - goto failure; - } - if (mount_fs(mount_dir, backing_dir, 50) != 0) - goto failure; - - cmd_fd = open_commands_file(mount_dir); - if (cmd_fd < 0) - goto failure; - - /* Validate data again */ - for (i = 0; i < file_num; i++) { - struct test_file *file = &test.files[i]; - int sig_len; - char *path; - int fd; - - if (validate_test_file_content(mount_dir, file) < 0) - goto failure; - - path = concat_file_name(mount_dir, file->name); - fd = open(path, O_RDWR); - free(path); - if (fd < 0) { - print_error("Can't open file"); - goto failure; - } - - sig_len = get_file_signature(fd, sig_buf, ARRAY_SIZE(sig_buf)); - - if (close(fd)) { - print_error("Can't close file"); - goto failure; - } - - if (sig_len < 0) { - ksft_print_msg("Can't load signature %s. error: %s\n", - file->name, strerror(-sig_len)); - goto failure; - } - if (sig_len != file->sig.size || - memcmp(sig_buf, file->sig.data, sig_len)) { - ksft_print_msg("Signature mismatch %s.\n", - file->name); - goto failure; - } - } - - /* Final unmount */ - close(cmd_fd); - cmd_fd = -1; - if (umount(mount_dir) != 0) { - print_error("Can't unmout FS"); - goto failure; - } - return TEST_SUCCESS; - -failure: - close(cmd_fd); - free(backing_dir); - umount(mount_dir); - return TEST_FAILURE; -} - static int hash_tree_test(char *mount_dir) { char *backing_dir; @@ -2066,8 +1838,8 @@ static int hash_tree_test(char *mount_dir) build_mtree(file); res = crypto_emit_file(cmd_fd, NULL, file->name, &file->id, - file->size, file->root_hash, - file->sig.data, file->sig.size, file->sig.add_data); + file->size, file->root_hash, + file->sig.add_data); if (i == corrupted_file_idx) { /* Corrupt third blocks hash */ @@ -2327,6 +2099,347 @@ failure: return TEST_FAILURE; } +static int emit_partial_test_file_data(char *mount_dir, struct test_file *file) +{ + int i, j; + int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE; + int *block_indexes = NULL; + int result = 0; + int blocks_written = 0; + + if (file->size == 0) + return 0; + + /* Emit 2 blocks, skip 2 blocks etc*/ + block_indexes = calloc(block_cnt, sizeof(*block_indexes)); + for (i = 0, j = 0; i < block_cnt; ++i) + if ((i & 2) == 0) { + block_indexes[j] = i; + ++j; + } + + for (i = 0; i < j; i += blocks_written) { + blocks_written = emit_test_blocks(mount_dir, file, + block_indexes + i, j - i); + if (blocks_written < 0) { + result = blocks_written; + goto out; + } + if (blocks_written == 0) { + result = -EIO; + goto out; + } + } +out: + free(block_indexes); + return result; +} + +static int validate_ranges(const char *mount_dir, struct test_file *file) +{ + int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE; + char *filename = concat_file_name(mount_dir, file->name); + int fd; + struct incfs_filled_range ranges[128]; + struct incfs_get_filled_blocks_args fba = { + .range_buffer = ptr_to_u64(ranges), + .range_buffer_size = sizeof(ranges), + }; + int error = TEST_SUCCESS; + int i; + int range_cnt; + + fd = open(filename, O_RDONLY); + free(filename); + if (fd <= 0) + return TEST_FAILURE; + + error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba); + if (error && errno != ERANGE) + goto out; + + if (error && errno == ERANGE && block_cnt < 509) + goto out; + + if (!error && block_cnt >= 509) { + error = -ERANGE; + goto out; + } + + if (fba.total_blocks_out != block_cnt) { + error = -EINVAL; + goto out; + } + + range_cnt = (block_cnt + 3) / 4; + if (range_cnt > 128) + range_cnt = 128; + if (range_cnt != fba.range_buffer_size_out / sizeof(*ranges)) { + error = -ERANGE; + goto out; + } + + error = TEST_SUCCESS; + for (i = 0; i < fba.range_buffer_size_out / sizeof(*ranges) - 1; ++i) + if (ranges[i].begin != i * 4 || ranges[i].end != i * 4 + 2) { + error = -EINVAL; + goto out; + } + + if (ranges[i].begin != i * 4 || + (ranges[i].end != i * 4 + 1 && ranges[i].end != i * 4 + 2)) { + error = -EINVAL; + goto out; + } + + for (i = 0; i < 64; ++i) { + fba.start_index = i * 2; + fba.end_index = i * 2 + 2; + error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba); + if (error) + goto out; + + if (fba.total_blocks_out != block_cnt) { + error = -EINVAL; + goto out; + } + + if (fba.start_index >= block_cnt) { + if (fba.index_out != fba.start_index) { + printf("Paul: %d, %d\n", (int)fba.index_out, + (int)fba.start_index); + error = -EINVAL; + goto out; + } + + break; + } + + if (i % 2) { + if (fba.range_buffer_size_out != 0) { + error = -EINVAL; + goto out; + } + } else { + if (fba.range_buffer_size_out != sizeof(*ranges)) { + error = -EINVAL; + goto out; + } + + if (ranges[0].begin != i * 2) { + error = -EINVAL; + goto out; + } + + if (ranges[0].end != i * 2 + 1 && + ranges[0].end != i * 2 + 2) { + error = -EINVAL; + goto out; + } + } + } + +out: + close(fd); + return error; +} + +static int get_blocks_test(char *mount_dir) +{ + char *backing_dir; + int cmd_fd = -1; + int i; + struct test_files_set test = get_test_files_set(); + const int file_num = test.files_count; + + backing_dir = create_backing_dir(mount_dir); + if (!backing_dir) + goto failure; + + if (mount_fs_opt(mount_dir, backing_dir, "readahead=0") != 0) + goto failure; + + cmd_fd = open_commands_file(mount_dir); + if (cmd_fd < 0) + goto failure; + + /* Write data. */ + for (i = 0; i < file_num; i++) { + struct test_file *file = &test.files[i]; + + if (emit_file(cmd_fd, NULL, file->name, &file->id, file->size, + NULL)) + goto failure; + + if (emit_partial_test_file_data(mount_dir, file)) + goto failure; + } + + for (i = 0; i < file_num; i++) { + struct test_file *file = &test.files[i]; + + if (validate_ranges(mount_dir, file)) + goto failure; + + /* + * The smallest files are filled completely, so this checks that + * the fast get_filled_blocks path is not causing issues + */ + if (validate_ranges(mount_dir, file)) + goto failure; + } + + close(cmd_fd); + umount(mount_dir); + free(backing_dir); + return TEST_SUCCESS; + +failure: + close(cmd_fd); + umount(mount_dir); + free(backing_dir); + return TEST_FAILURE; +} + +static int emit_partial_test_file_hash(char *mount_dir, struct test_file *file) +{ + int err; + int fd; + struct incfs_fill_blocks fill_blocks = { + .count = 1, + }; + struct incfs_fill_block *fill_block_array = + calloc(fill_blocks.count, sizeof(struct incfs_fill_block)); + uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE]; + + if (file->size <= 4096 / 32 * 4096) + return 0; + + if (fill_blocks.count == 0) + return 0; + + if (!fill_block_array) + return -ENOMEM; + fill_blocks.fill_blocks = ptr_to_u64(fill_block_array); + + rnd_buf(data, sizeof(data), 0); + + fill_block_array[0] = + (struct incfs_fill_block){ .block_index = 1, + .data_len = + INCFS_DATA_FILE_BLOCK_SIZE, + .data = ptr_to_u64(data), + .flags = INCFS_BLOCK_FLAGS_HASH }; + + fd = open_file_by_id(mount_dir, file->id, true); + if (fd < 0) { + err = errno; + goto failure; + } + + err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks); + close(fd); + if (err < fill_blocks.count) + err = errno; + else + err = 0; + +failure: + free(fill_block_array); + return err; +} + +static int validate_hash_ranges(const char *mount_dir, struct test_file *file) +{ + char *filename = concat_file_name(mount_dir, file->name); + int fd; + struct incfs_filled_range ranges[128]; + struct incfs_get_filled_blocks_args fba = { + .range_buffer = ptr_to_u64(ranges), + .range_buffer_size = sizeof(ranges), + }; + int error = TEST_SUCCESS; + int file_blocks = (file->size + INCFS_DATA_FILE_BLOCK_SIZE - 1) / + INCFS_DATA_FILE_BLOCK_SIZE; + + if (file->size <= 4096 / 32 * 4096) + return 0; + + fd = open(filename, O_RDONLY); + free(filename); + if (fd <= 0) + return TEST_FAILURE; + + error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba); + if (error) + goto out; + + if (fba.range_buffer_size_out != sizeof(struct incfs_filled_range)) { + error = -EINVAL; + goto out; + } + + if (ranges[0].begin != file_blocks + 1 || + ranges[0].end != file_blocks + 2) { + error = -EINVAL; + goto out; + } + +out: + close(fd); + return error; +} + +static int get_hash_blocks_test(char *mount_dir) +{ + char *backing_dir; + int cmd_fd = -1; + int i; + struct test_files_set test = get_test_files_set(); + const int file_num = test.files_count; + + backing_dir = create_backing_dir(mount_dir); + if (!backing_dir) + goto failure; + + if (mount_fs_opt(mount_dir, backing_dir, "readahead=0") != 0) + goto failure; + + cmd_fd = open_commands_file(mount_dir); + if (cmd_fd < 0) + goto failure; + + for (i = 0; i < file_num; i++) { + struct test_file *file = &test.files[i]; + + if (crypto_emit_file(cmd_fd, NULL, file->name, &file->id, + file->size, file->root_hash, + file->sig.add_data)) + goto failure; + + if (emit_partial_test_file_hash(mount_dir, file)) + goto failure; + } + + for (i = 0; i < file_num; i++) { + struct test_file *file = &test.files[i]; + + if (validate_hash_ranges(mount_dir, file)) + goto failure; + } + + close(cmd_fd); + umount(mount_dir); + free(backing_dir); + return TEST_SUCCESS; + +failure: + close(cmd_fd); + umount(mount_dir); + free(backing_dir); + return TEST_FAILURE; +} + static char *setup_mount_dir() { struct stat st; @@ -2392,9 +2505,10 @@ int main(int argc, char *argv[]) MAKE_TEST(work_after_remount_test), MAKE_TEST(child_procs_waiting_for_data_test), MAKE_TEST(multiple_providers_test), - MAKE_TEST(signature_test), MAKE_TEST(hash_tree_test), MAKE_TEST(read_log_test), + MAKE_TEST(get_blocks_test), + MAKE_TEST(get_hash_blocks_test), }; #undef MAKE_TEST diff --git a/tools/testing/selftests/filesystems/incfs/utils.c b/tools/testing/selftests/filesystems/incfs/utils.c index 08b8452ad0bc..3a72fa5d5e9a 100644 --- a/tools/testing/selftests/filesystems/incfs/utils.c +++ b/tools/testing/selftests/filesystems/incfs/utils.c @@ -23,7 +23,8 @@ #include "utils.h" -int mount_fs(char *mount_dir, char *backing_dir, int read_timeout_ms) +int mount_fs(const char *mount_dir, const char *backing_dir, + int read_timeout_ms) { static const char fs_name[] = INCFS_NAME; char mount_options[512]; @@ -39,7 +40,8 @@ int mount_fs(char *mount_dir, char *backing_dir, int read_timeout_ms) return result; } -int mount_fs_opt(char *mount_dir, char *backing_dir, char *opt) +int mount_fs_opt(const char *mount_dir, const char *backing_dir, + const char *opt) { static const char fs_name[] = INCFS_NAME; int result; @@ -50,179 +52,94 @@ int mount_fs_opt(char *mount_dir, char *backing_dir, char *opt) return result; } -int unlink_node(int fd, int parent_ino, char *filename) +struct hash_section { + uint32_t algorithm; + uint8_t log2_blocksize; + uint32_t salt_size; + /* no salt */ + uint32_t hash_size; + uint8_t hash[SHA256_DIGEST_SIZE]; +} __packed; + +struct signature_blob { + uint32_t version; + uint32_t hash_section_size; + struct hash_section hash_section; + uint32_t signing_section_size; + uint8_t signing_section[]; +} __packed; + +size_t format_signature(void **buf, const char *root_hash, const char *add_data) { - return 0; + size_t size = sizeof(struct signature_blob) + strlen(add_data) + 1; + struct signature_blob *sb = malloc(size); + + *sb = (struct signature_blob){ + .version = INCFS_SIGNATURE_VERSION, + .hash_section_size = sizeof(struct hash_section), + .hash_section = + (struct hash_section){ + .algorithm = INCFS_HASH_TREE_SHA256, + .log2_blocksize = 12, + .salt_size = 0, + .hash_size = SHA256_DIGEST_SIZE, + }, + .signing_section_size = sizeof(uint32_t) + strlen(add_data) + 1, + }; + + memcpy(sb->hash_section.hash, root_hash, SHA256_DIGEST_SIZE); + memcpy((char *)sb->signing_section, add_data, strlen(add_data) + 1); + *buf = sb; + return size; } - -static EVP_PKEY *deserialize_private_key(const char *pem_key) -{ - BIO *bio = NULL; - EVP_PKEY *pkey = NULL; - int len = strlen(pem_key); - - bio = BIO_new_mem_buf(pem_key, len); - if (!bio) - return NULL; - - pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); - BIO_free(bio); - return pkey; -} - -static X509 *deserialize_cert(const char *pem_cert) -{ - BIO *bio = NULL; - X509 *cert = NULL; - int len = strlen(pem_cert); - - bio = BIO_new_mem_buf(pem_cert, len); - if (!bio) - return NULL; - - cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); - BIO_free(bio); - return cert; -} - -bool sign_pkcs7(const void *data_to_sign, size_t data_size, - char *pkey_pem, char *cert_pem, - void **sig_ret, size_t *sig_size_ret) -{ - /* - * PKCS#7 signing flags: - * - * - PKCS7_BINARY signing binary data, so skip MIME translation - * - * - PKCS7_NOATTR omit extra authenticated attributes, such as - * SMIMECapabilities - * - * - PKCS7_PARTIAL PKCS7_sign() creates a handle only, then - * PKCS7_sign_add_signer() can add a signer later. - * This is necessary to change the message digest - * algorithm from the default of SHA-1. Requires - * OpenSSL 1.0.0 or later. - */ - int pkcs7_flags = PKCS7_BINARY | PKCS7_NOATTR | PKCS7_PARTIAL; - void *sig; - size_t sig_size; - BIO *bio = NULL; - PKCS7 *p7 = NULL; - EVP_PKEY *pkey = NULL; - X509 *cert = NULL; - bool ok = false; - - const EVP_MD *md = EVP_sha256(); - - pkey = deserialize_private_key(pkey_pem); - if (!pkey) { - printf("deserialize_private_key failed\n"); - goto out; - } - - cert = deserialize_cert(cert_pem); - if (!cert) { - printf("deserialize_cert failed\n"); - goto out; - } - - bio = BIO_new_mem_buf(data_to_sign, data_size); - if (!bio) - goto out; - - p7 = PKCS7_sign(NULL, NULL, NULL, bio, pkcs7_flags); - if (!p7) { - printf("failed to initialize PKCS#7 signature object\n"); - goto out; - } - - if (!PKCS7_sign_add_signer(p7, cert, pkey, md, pkcs7_flags)) { - printf("failed to add signer to PKCS#7 signature object\n"); - goto out; - } - - if (PKCS7_final(p7, bio, pkcs7_flags) != 1) { - printf("failed to finalize PKCS#7 signature\n"); - goto out; - } - - BIO_free(bio); - bio = BIO_new(BIO_s_mem()); - if (!bio) { - printf("out of memory\n"); - goto out; - } - - if (i2d_PKCS7_bio(bio, p7) != 1) { - printf("failed to DER-encode PKCS#7 signature object\n"); - goto out; - } - - sig_size = BIO_get_mem_data(bio, &sig); - *sig_ret = malloc(sig_size); - memcpy(*sig_ret, sig, sig_size); - *sig_size_ret = sig_size; - ok = true; -out: - PKCS7_free(p7); - BIO_free(bio); - return ok; -} - -int crypto_emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out, - size_t size, const char *root_hash, char *sig, size_t sig_size, - char *add_data) +int crypto_emit_file(int fd, const char *dir, const char *filename, + incfs_uuid_t *id_out, size_t size, const char *root_hash, + const char *add_data) { int mode = __S_IFREG | 0555; - struct incfs_file_signature_info sig_info = { - .hash_tree_alg = root_hash - ? INCFS_HASH_TREE_SHA256 - : 0, - .root_hash = ptr_to_u64(root_hash), - .additional_data = ptr_to_u64(add_data), - .additional_data_size = strlen(add_data), - .signature = ptr_to_u64(sig), - .signature_size = sig_size, - }; + void *signature; + int error = 0; struct incfs_new_file_args args = { .size = size, .mode = mode, .file_name = ptr_to_u64(filename), .directory_path = ptr_to_u64(dir), - .signature_info = ptr_to_u64(&sig_info), .file_attr = 0, .file_attr_len = 0 }; + args.signature_size = format_signature(&signature, root_hash, add_data); + args.signature_info = ptr_to_u64(signature); + md5(filename, strlen(filename), (char *)args.file_id.bytes); - if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0) - return -errno; + if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0) { + error = -errno; + goto out; + } *id_out = args.file_id; - return 0; + +out: + free(signature); + return error; } - -int emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out, - size_t size, char *attr) +int emit_file(int fd, const char *dir, const char *filename, + incfs_uuid_t *id_out, size_t size, const char *attr) { int mode = __S_IFREG | 0555; - struct incfs_file_signature_info sig_info = { - .hash_tree_alg = 0, - .root_hash = ptr_to_u64(NULL) - }; - struct incfs_new_file_args args = { - .size = size, - .mode = mode, - .file_name = ptr_to_u64(filename), - .directory_path = ptr_to_u64(dir), - .signature_info = ptr_to_u64(&sig_info), - .file_attr = ptr_to_u64(attr), - .file_attr_len = attr ? strlen(attr) : 0 - }; + struct incfs_new_file_args args = { .size = size, + .mode = mode, + .file_name = ptr_to_u64(filename), + .directory_path = ptr_to_u64(dir), + .signature_info = ptr_to_u64(NULL), + .signature_size = 0, + .file_attr = ptr_to_u64(attr), + .file_attr_len = + attr ? strlen(attr) : 0 }; md5(filename, strlen(filename), (char *)args.file_id.bytes); @@ -250,7 +167,7 @@ int get_file_signature(int fd, unsigned char *buf, int buf_size) return -errno; } -loff_t get_file_size(char *name) +loff_t get_file_size(const char *name) { struct stat st; @@ -259,7 +176,7 @@ loff_t get_file_size(char *name) return -ENOENT; } -int open_commands_file(char *mount_dir) +int open_commands_file(const char *mount_dir) { char cmd_file[255]; int cmd_fd; @@ -273,7 +190,7 @@ int open_commands_file(char *mount_dir) return cmd_fd; } -int open_log_file(char *mount_dir) +int open_log_file(const char *mount_dir) { char cmd_file[255]; int cmd_fd; @@ -358,7 +275,7 @@ out: return result; } -void sha256(char *data, size_t dsize, char *hash) +void sha256(const char *data, size_t dsize, char *hash) { SHA256_CTX ctx; @@ -367,7 +284,7 @@ void sha256(char *data, size_t dsize, char *hash) SHA256_Final((unsigned char *)hash, &ctx); } -void md5(char *data, size_t dsize, char *hash) +void md5(const char *data, size_t dsize, char *hash) { MD5_CTX ctx; diff --git a/tools/testing/selftests/filesystems/incfs/utils.h b/tools/testing/selftests/filesystems/incfs/utils.h index 9c9ba3c5f70a..23c8a099662a 100644 --- a/tools/testing/selftests/filesystems/incfs/utils.h +++ b/tools/testing/selftests/filesystems/incfs/utils.h @@ -9,6 +9,8 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) +#define __packed __attribute__((__packed__)) + #ifdef __LP64__ #define ptr_to_u64(p) ((__u64)p) #else @@ -17,9 +19,11 @@ #define SHA256_DIGEST_SIZE 32 -int mount_fs(char *mount_dir, char *backing_dir, int read_timeout_ms); +int mount_fs(const char *mount_dir, const char *backing_dir, + int read_timeout_ms); -int mount_fs_opt(char *mount_dir, char *backing_dir, char *opt); +int mount_fs_opt(const char *mount_dir, const char *backing_dir, + const char *opt); int get_file_bmap(int cmd_fd, int ino, unsigned char *buf, int buf_size); @@ -28,32 +32,26 @@ int get_file_signature(int fd, unsigned char *buf, int buf_size); int emit_node(int fd, char *filename, int *ino_out, int parent_ino, size_t size, mode_t mode, char *attr); -int emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out, - size_t size, char *attr); +int emit_file(int fd, const char *dir, const char *filename, + incfs_uuid_t *id_out, size_t size, const char *attr); -int crypto_emit_file(int fd, char *dir, char *filename, incfs_uuid_t *id_out, - size_t size, const char *root_hash, char *sig, size_t sig_size, - char *add_data); +int crypto_emit_file(int fd, const char *dir, const char *filename, + incfs_uuid_t *id_out, size_t size, const char *root_hash, + const char *add_data); -int unlink_node(int fd, int parent_ino, char *filename); +loff_t get_file_size(const char *name); -loff_t get_file_size(char *name); +int open_commands_file(const char *mount_dir); -int open_commands_file(char *mount_dir); - -int open_log_file(char *mount_dir); +int open_log_file(const char *mount_dir); int wait_for_pending_reads(int fd, int timeout_ms, struct incfs_pending_read_info *prs, int prs_count); char *concat_file_name(const char *dir, char *file); -void sha256(char *data, size_t dsize, char *hash); +void sha256(const char *data, size_t dsize, char *hash); -void md5(char *data, size_t dsize, char *hash); - -bool sign_pkcs7(const void *data_to_sign, size_t data_size, - char *pkey_pem, char *cert_pem, - void **sig_ret, size_t *sig_size_ret); +void md5(const char *data, size_t dsize, char *hash); int delete_dir_tree(const char *path); diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk index 1c8a1963d03f..3ed0134a764d 100644 --- a/tools/testing/selftests/lib.mk +++ b/tools/testing/selftests/lib.mk @@ -83,17 +83,20 @@ else $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS)) endif +define INSTALL_SINGLE_RULE + $(if $(INSTALL_LIST),@mkdir -p $(INSTALL_PATH)) + $(if $(INSTALL_LIST),@echo rsync -a $(INSTALL_LIST) $(INSTALL_PATH)/) + $(if $(INSTALL_LIST),@rsync -a $(INSTALL_LIST) $(INSTALL_PATH)/) +endef + define INSTALL_RULE - @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \ - mkdir -p ${INSTALL_PATH}; \ - echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/"; \ - rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/; \ - fi - @if [ "X$(TEST_GEN_PROGS)$(TEST_CUSTOM_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then \ - mkdir -p ${INSTALL_PATH}; \ - echo "rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/"; \ - rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/; \ - fi + $(eval INSTALL_LIST = $(TEST_PROGS)) $(INSTALL_SINGLE_RULE) + $(eval INSTALL_LIST = $(TEST_PROGS_EXTENDED)) $(INSTALL_SINGLE_RULE) + $(eval INSTALL_LIST = $(TEST_FILES)) $(INSTALL_SINGLE_RULE) + $(eval INSTALL_LIST = $(TEST_GEN_PROGS)) $(INSTALL_SINGLE_RULE) + $(eval INSTALL_LIST = $(TEST_CUSTOM_PROGS)) $(INSTALL_SINGLE_RULE) + $(eval INSTALL_LIST = $(TEST_GEN_PROGS_EXTENDED)) $(INSTALL_SINGLE_RULE) + $(eval INSTALL_LIST = $(TEST_GEN_FILES)) $(INSTALL_SINGLE_RULE) endef install: all diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh index 474638ef2697..09854f8a0b57 100755 --- a/tools/testing/selftests/net/fib_tests.sh +++ b/tools/testing/selftests/net/fib_tests.sh @@ -1041,6 +1041,27 @@ ipv6_addr_metric_test() fi log_test $rc 0 "Prefix route with metric on link up" + # verify peer metric added correctly + set -e + run_cmd "$IP -6 addr flush dev dummy2" + run_cmd "$IP -6 addr add dev dummy2 2001:db8:104::1 peer 2001:db8:104::2 metric 260" + set +e + + check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260" + log_test $? 0 "Set metric with peer route on local side" + log_test $? 0 "User specified metric on local address" + check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260" + log_test $? 0 "Set metric with peer route on peer side" + + set -e + run_cmd "$IP -6 addr change dev dummy2 2001:db8:104::1 peer 2001:db8:104::3 metric 261" + set +e + + check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 261" + log_test $? 0 "Modify metric and peer address on local side" + check_route6 "2001:db8:104::3 dev dummy2 proto kernel metric 261" + log_test $? 0 "Modify metric and peer address on peer side" + $IP li del dummy1 $IP li del dummy2 cleanup @@ -1457,13 +1478,20 @@ ipv4_addr_metric_test() run_cmd "$IP addr flush dev dummy2" run_cmd "$IP addr add dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 260" - run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.2 metric 261" rc=$? if [ $rc -eq 0 ]; then - check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261" + check_route "172.16.104.2 dev dummy2 proto kernel scope link src 172.16.104.1 metric 260" rc=$? fi - log_test $rc 0 "Modify metric of address with peer route" + log_test $rc 0 "Set metric of address with peer route" + + run_cmd "$IP addr change dev dummy2 172.16.104.1/32 peer 172.16.104.3 metric 261" + rc=$? + if [ $rc -eq 0 ]; then + check_route "172.16.104.3 dev dummy2 proto kernel scope link src 172.16.104.1 metric 261" + rc=$? + fi + log_test $rc 0 "Modify metric and peer address for peer route" $IP li del dummy1 $IP li del dummy2 diff --git a/tools/testing/selftests/net/forwarding/mirror_gre.sh b/tools/testing/selftests/net/forwarding/mirror_gre.sh index e6fd7a18c655..0266443601bc 100755 --- a/tools/testing/selftests/net/forwarding/mirror_gre.sh +++ b/tools/testing/selftests/net/forwarding/mirror_gre.sh @@ -63,22 +63,23 @@ test_span_gre_mac() { local tundev=$1; shift local direction=$1; shift - local prot=$1; shift local what=$1; shift - local swp3mac=$(mac_get $swp3) - local h3mac=$(mac_get $h3) + case "$direction" in + ingress) local src_mac=$(mac_get $h1); local dst_mac=$(mac_get $h2) + ;; + egress) local src_mac=$(mac_get $h2); local dst_mac=$(mac_get $h1) + ;; + esac RET=0 mirror_install $swp1 $direction $tundev "matchall $tcflags" - tc filter add dev $h3 ingress pref 77 prot $prot \ - flower ip_proto 0x2f src_mac $swp3mac dst_mac $h3mac \ - action pass + icmp_capture_install h3-${tundev} "src_mac $src_mac dst_mac $dst_mac" - mirror_test v$h1 192.0.2.1 192.0.2.2 $h3 77 10 + mirror_test v$h1 192.0.2.1 192.0.2.2 h3-${tundev} 100 10 - tc filter del dev $h3 ingress pref 77 + icmp_capture_uninstall h3-${tundev} mirror_uninstall $swp1 $direction log_test "$direction $what: envelope MAC ($tcflags)" @@ -120,14 +121,14 @@ test_ip6gretap() test_gretap_mac() { - test_span_gre_mac gt4 ingress ip "mirror to gretap" - test_span_gre_mac gt4 egress ip "mirror to gretap" + test_span_gre_mac gt4 ingress "mirror to gretap" + test_span_gre_mac gt4 egress "mirror to gretap" } test_ip6gretap_mac() { - test_span_gre_mac gt6 ingress ipv6 "mirror to ip6gretap" - test_span_gre_mac gt6 egress ipv6 "mirror to ip6gretap" + test_span_gre_mac gt6 ingress "mirror to ip6gretap" + test_span_gre_mac gt6 egress "mirror to ip6gretap" } test_all() diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh index bb10e33690b2..ce6bea9675c0 100755 --- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh +++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh @@ -516,9 +516,9 @@ test_tos() RET=0 tc filter add dev v1 egress pref 77 prot ip \ - flower ip_tos 0x40 action pass - vxlan_ping_test $h1 192.0.2.3 "-Q 0x40" v1 egress 77 10 - vxlan_ping_test $h1 192.0.2.3 "-Q 0x30" v1 egress 77 0 + flower ip_tos 0x14 action pass + vxlan_ping_test $h1 192.0.2.3 "-Q 0x14" v1 egress 77 10 + vxlan_ping_test $h1 192.0.2.3 "-Q 0x18" v1 egress 77 0 tc filter del dev v1 egress pref 77 prot ip log_test "VXLAN: envelope TOS inheritance" diff --git a/tools/testing/selftests/rseq/Makefile b/tools/testing/selftests/rseq/Makefile index f1053630bb6f..2af9d39a9716 100644 --- a/tools/testing/selftests/rseq/Makefile +++ b/tools/testing/selftests/rseq/Makefile @@ -4,7 +4,7 @@ ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) CLANG_FLAGS += -no-integrated-as endif -CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L./ -Wl,-rpath=./ \ +CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L$(OUTPUT) -Wl,-rpath=./ \ $(CLANG_FLAGS) LDLIBS += -lpthread diff --git a/usr/include/Makefile b/usr/include/Makefile index 47cb91d3a51d..e2840579156a 100644 --- a/usr/include/Makefile +++ b/usr/include/Makefile @@ -99,7 +99,7 @@ endif # asm-generic/*.h is used by asm/*.h, and should not be included directly header-test- += asm-generic/% -extra-y := $(patsubst $(obj)/%.h,%.hdrtest, $(shell find $(obj) -name '*.h')) +extra-y := $(patsubst $(obj)/%.h,%.hdrtest, $(shell find $(obj) -name '*.h' 2>/dev/null)) quiet_cmd_hdrtest = HDRTEST $< cmd_hdrtest = \